枚举变的花,把花挪到最后面,然后再算。
算先统计之前有多少个两个花重叠的部分,如果这朵花走了过后说明这些地方就要加上了(因为走了一个,所以只有一个了)。再加上新多出来的个数。
先问一下思路有没有问题。
下面是代码:
#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;
}
//先离散化一下
//然后差分
//对于每个玫瑰,枚举,然后把他的时间放到最后面
//计算每个玫瑰挪走后能增加多少就可以了