CF580B
题目简化和分析:
选择 \(n\) 个朋友,满足以下条件:
- 工资差异 \(<d\)
- 友谊和最大(题目翻译不太清楚)
现在面临两个问题
- 求差异值
- 求友谊和
所以我们理应想到线段树双指针。
排序后满足工资从小到大,友谊和可以用前缀和实现。
每次往后加一个人。
用 while 循环,增加左端点,使得工资差异满足。
并且每次取最大值最后输出。
两个指针,如果一直满足就增加右端点,否则增加左端点,可以保证差异值并且长度最大,然后每次在此区间打擂台即可。
Solution:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+50;
const int M=1e5+50;
const int Mod=1e9+7;
inline ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
ll n,d;
struct node{
ll m,s;
}a[N];
ll ans;
ll s[N];
bool cmp(node a,node b){
return a.m<b.m;
}
int main()
{
n=read(),d=read();
for(int i=1;i<=n;++i){
a[i].m=read(),a[i].s=read();
}
sort(a+1,a+n+1,cmp);
ll l=1;
for(int i=1;i<=n;++i){
s[i]=s[i-1]+a[i].s;
while(a[i].m-a[l].m>=d) ++l;
ans=max(ans,s[i]-s[l-1]);
}
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号