专栏文章
8-3陈老师课堂总结--程皓楠
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miojaah3
- 此快照首次捕获于
- 2025/12/02 20:07 3 个月前
- 此快照最后确认于
- 2025/12/02 20:07 3 个月前
P1102 A-B 数对
函数代替手写
1. lower_bound(a+1,a+1+n,x)-a这个函数能够求出最小的满足a[i]>=x的地址,但我们要求下标,所以要用地址-地址=下标
2. upper_bound(a+1,a+1+n,x)-a这个函数能够求出最小的满足a[i]>x的地址,但我们要求下标所以要用地址-地址=下标
题目思路
我们可以把A-B=C转化成A-C=B,然后一定要变成有序序列,然后用二分第一个大于b的下标-第一个大于等于b的下标从而求出b的个数
AC代码
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,c;
cin>>n>>c;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
int sum=0;
for(int i=1;i<=n;i++)sum+=(upper_bound(a+1,a+1+n,a[i]-c)-lower_bound(a+1,a+1+n,a[i]-c));
cout<<sum;
return 0;
}
A-CF1006C Three Parts of the Array
简化题意
给定一个长度为n的数列d,你需要将它分成从左到右3个连续的子数列,每个数字属于且仅属于其中一个子数列。要求第一个数列的元素值之和sum1等于第三个数列元素之和sum3。第二个数列可以没有元素。求sum1的最大值。
题目思路
通过题意,我们可以发现我们重点研究的是sum1和sum3,sum2并无大用。看到和,我们立即可以立即想到前缀和,然而这道题的数据大小又让我们想到O(nlogn),所以这道题的算法我们可以猜到是前缀和+二分
我们可以先算出数列d的前缀和,然后判断若二分出第一个大于等于s[n]-s[i+1]的值的下标>=i并且s[n]-s[i+1]要等于[1,二分的值的下标]之和就废止
AC代码
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+5;
int s[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,ans=0;
cin>>n;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
s[i]=s[i-1]+x;
}
for(int i=1;i<=n;i++)
{
int l=i+1,r=n;
int pos=lower_bound(s+1,s+1+n,s[r]-s[l-1])-s;
if(pos>=i&&s[pos]==s[r]-s[l-1])ans=s[i];
}
cout<<ans;
return 0;
}
B-Glider
题目思路
这道题目我们可以枚举起跳的点,在这之前,我们用两个前缀和求出变的距离和不变的距离,然后二分高度,由于下降的距离是已知的,所以我们要取不下降距离的最大值,每次都用二分高度的下标-起跳点,取最大和,最后输出用不下降最大距离+下降距离
AC代码
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int s[N],e[N],sum[N],pre[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>s[i]>>e[i];
if(i>1)sum[i]=sum[i-1]+(s[i]-e[i-1]);
pre[i]=pre[i-1]+(e[i]-s[i]);
}
int ans=0;
for(int i=1;i<=n;i++)
{
int pos=lower_bound(sum+i+1,sum+1+n,sum[i]+k)-sum-1;
ans=max(ans,(pre[pos]-pre[i-1]));
}
cout<<ans+k;
return 0;
}
C - Romantic Glasses
题目思路
用两个前缀和求出奇数下标和,还有偶数下标和,然后用桶统计sum1[r]-sum2[r]的差出现了几次,找出重复的差,若有就输出YES,等循环结束后,若还没输出YES,则输出NO
AC代码
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+5;
int a[N],sum1[N],sum2[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T--)
{
map<int,int> mp;
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(i%2==1)
{
sum1[i]=sum1[i-1]+a[i];
sum2[i]=sum2[i-1];
}
else
{
sum2[i]=sum2[i-1]+a[i];
sum1[i]=sum1[i-1];
}
}
bool f=1;
for(int r=0;r<=n;r++)
{
mp[sum1[r]-sum2[r]]++;
if(mp[sum1[r]-sum2[r]]>1)
{
cout<<"YES\n";
f=0;
break;
}
}
if(f)cout<<"NO\n";
mp.clear();
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...