CF580B

题目简化和分析:

选择 \(n\) 个朋友,满足以下条件:

  • 工资差异 \(<d\)
  • 友谊和最大(题目翻译不太清楚)

现在面临两个问题

  1. 求差异值
  2. 求友谊和

所以我们理应想到线段树双指针。

排序后满足工资从小到大,友谊和可以用前缀和实现。

每次往后加一个人。
用 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;
}

posted @ 2022-08-02 20:51  RVG  阅读(35)  评论(0)    收藏  举报