求助65pts
查看原帖
求助65pts
1220111
xiaoyang222楼主2024/8/3 18:15

枚举变的花,把花挪到最后面,然后再算。

算先统计之前有多少个两个花重叠的部分,如果这朵花走了过后说明这些地方就要加上了(因为走了一个,所以只有一个了)。再加上新多出来的个数。

先问一下思路有没有问题。

下面是代码:

#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#define int long long
using namespace std;
const int N=2e5+5,M=1e6+5;
int n,m;
int t[N];
map<int,int> ma;
int d[M];//差分(后半部分是这段时间能加多少贡献)
int sm2[M];
int f[M];//离散化前的时间
signed main(){
	cin >> n >> m;
	set<int> s;
//	for (int i=0;i<=2e5;++i) s.insert(i);
	for (int i=1;i<=n;++i){
		scanf("%lld",&t[i]);
		s.insert(t[i]);
		s.insert(t[i]+m-1);
		s.insert(t[i]-1);//因为前缀和的时候会访问到前面的
//		s.insert(t[i]+1);
//		s.insert(t[i]+m);
//		s.insert(t[i]+m-2);
	}
	int tot=1;
	for (const int t:s){
		f[tot]=t;ma[t]=tot;
		++tot;
	}
	int x,x2;
	for (int i=1;i<=n;++i){
		x=ma[t[i]],x2=ma[t[i]+m-1];
		++d[x],--d[x2+1];
	}
	for (int i=1;i<=tot;++i) d[i]+=d[i-1];
	int ans=0;
	for (int i=1;i<=tot;++i){
		if (d[i]==1) ans+=f[i]-f[i-1],sm2[i]=1;//只有一个
		if (d[i]==2) d[i]=f[i]-f[i-1];
		else d[i]=0;
	}
	for (int i=1;i<=tot;++i) d[i]+=d[i-1],sm2[i]+=sm2[i-1];
	int res=ans;
	for (int i=1;i<=n;++i){
//		cout<<i<<" "<<ans+get(t[i],t[i]+m-1)<<endl;
//		cout<<get(t[i],t[i]+m-1)<<endl;
//		if (ma[t[i]+m-1]!=t[i]+m-1 || ma[t[i]]!=t[i]) return 114514;
		res=max(res,ans+(d[ma[t[i]+m-1]]-d[ma[t[i]]-1])-(sm2[ma[t[i]+m-1]]-sm2[ma[t[i]]-1])+m);
	}
	cout<<res<<endl;
	return 0;
}
//先离散化一下
//然后差分
//对于每个玫瑰,枚举,然后把他的时间放到最后面
//计算每个玫瑰挪走后能增加多少就可以了
2024/8/3 18:15
加载中...