LOJ6777
_SeeleVollerei_ · · 个人记录
考虑维护没火的连续段。
可以证明,每次暴力枚举所有连续段并缩减,复杂度上界为
考虑证明。
首先每次操作只会贡献
对于
对于
到了这里就可以对连续段根号分治,可行但没必要。
因为这两个结论往下推一下你就会发现,每一时刻连续段个数就是
所以每次直接暴力枚举所有连续段。
那么后两个操作就是分裂连续段,以及合并若干个连续的连续段。
剩下的操作相当于,加一个区间的点,删
可以线段树,但是 pushdown。分析一下会发现是均摊
实现上拿个 vector 存连续段,然后写个分块就行了,很好写。
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> pr;
const int N=1e5+5;
const int block=320;
const int M=320;
int n,q;
inline int Read(){
char ch;
int f=1;
while((ch=getchar())<'0'||ch>'9')
if(ch=='-') f=-1;
int x=ch^48;
while((ch=getchar())>='0'&&ch<='9')
x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void print(LL x){
if(x>=10) print(x/10);
putchar(x%10+48);
return ;
}
inline void Print(LL x,char ch='\n'){
if(x<0){
putchar('-');
print(-x);
}
else print(x);
putchar(ch);
return ;
}
inline int Max(int x,int y){
return x>y?x:y;
}
inline int Min(int x,int y){
return x<y?x:y;
}
inline void Cmax(int&x,int y){
if(y>x) x=y;
return ;
}
inline void Cmin(int&x,int y){
if(y<x) x=y;
return ;
}
struct DS{
LL val[N],sum[M],tag[M];
bool tagvis[M];
LL tagall[M];
int cnt[M];
bool vis[N];
int bl[M],br[M],t;
int pos[N];
inline void Init(){
while(br[t]<n){
++t;
bl[t]=br[t-1]+1;
br[t]=Min(bl[t]+block-1,n);
for(int i=bl[t];i<=br[t];i++){
pos[i]=t;
val[i]=Read();
sum[t]+=val[i];
vis[i]=1;
}
cnt[t]=br[t]-bl[t]+1;
}
return ;
}
inline void PushDown(int p){
if(tag[p]){
for(int i=bl[p];i<=br[p];i++)
if(vis[i]) val[i]+=tag[p];
tag[p]=0;
}
if(tagall[p]){
for(int i=bl[p];i<=br[p];i++)
val[i]+=tagall[p];
tagall[p]=0;
}
if(tagvis[p]){
cnt[p]=br[p]-bl[p]+1;
for(int i=bl[p];i<=br[p];i++)
vis[i]=1;
tagvis[p]=0;
}
return ;
}
inline void Add(int ql,int qr,int value){
int p=pos[ql],q=pos[qr];
if(p==q){
PushDown(p);
for(int i=ql;i<=qr;i++)
if(vis[i]){
val[i]+=value;
sum[p]+=value;
}
return ;
}
PushDown(p);
for(int i=ql;i<=br[p];i++)
if(vis[i]){
val[i]+=value;
sum[p]+=value;
}
for(int i=p+1;i<=q-1;i++)
if(tagvis[i]){
sum[i]+=1ll*value*(br[i]-bl[i]+1);
tagall[i]+=value;
}
else{
sum[i]+=1ll*value*cnt[i];
tag[i]+=value;
}
PushDown(q);
for(int i=bl[q];i<=qr;i++)
if(vis[i]){
val[i]+=value;
sum[q]+=value;
}
return ;
}
inline void Add(int ql,int qr){
int p=pos[ql],q=pos[qr];
if(p==q){
PushDown(p);
for(int i=ql;i<=qr;i++)
if(!vis[i]){
vis[i]=1;
cnt[p]++;
}
return ;
}
PushDown(p);
for(int i=ql;i<=br[p];i++)
if(!vis[i]){
vis[i]=1;
cnt[p]++;
}
for(int i=p+1;i<=q-1;i++)
tagvis[i]=1;
PushDown(q);
for(int i=bl[q];i<=qr;i++)
if(!vis[i]){
vis[i]=1;
cnt[q]++;
}
return ;
}
inline void Del(int x){
int p=pos[x];
PushDown(p);
if(vis[x]){
sum[p]-=val[x];
cnt[p]--;
val[x]=vis[x]=0;
}
return ;
}
inline LL Query(int ql,int qr){
LL ss=0;
int p=pos[ql],q=pos[qr];
if(p==q){
PushDown(p);
for(int i=ql;i<=qr;i++)
if(vis[i]) ss+=val[i];
return ss;
}
PushDown(p);
for(int i=ql;i<=br[p];i++)
if(vis[i]) ss+=val[i];
for(int i=p+1;i<=q-1;i++)
ss+=sum[i];
PushDown(q);
for(int i=bl[q];i<=qr;i++)
if(vis[i]) ss+=val[i];
return ss;
}
}ds;
vector<pr>in;
vector<pr>in1;
inline void WorkFire(){
in1.clear();
for(int i=0;i<in.size();i++){
int l=in[i].first,r=in[i].second;
if(l!=1) ds.Del(l++);
if(r!=n) ds.Del(r--);
if(l<=r) in1.push_back(make_pair(l,r));
}
in=in1;
return ;
}
inline void AddFire(int x){
in1.clear();
ds.Del(x);
for(int i=0;i<in.size();i++){
int l=in[i].first,r=in[i].second;
if(x>r||x<l) in1.push_back(make_pair(l,r));
else{
if(x>l) in1.push_back(make_pair(l,x-1));
if(x<r) in1.push_back(make_pair(x+1,r));
}
}
in=in1;
return ;
}
inline void Clear(int ql,int qr){
in1.clear();
ds.Add(ql,qr);
int i=0;
while(i<in.size()&&in[i].second<ql-1)
in1.push_back(in[i++]);
int nowl=ql,nowr=qr;
while(i<in.size()&&in[i].first<=qr+1){
Cmin(nowl,in[i].first);
Cmax(nowr,in[i].second);
i++;
}
in1.push_back(make_pair(nowl,nowr));
while(i<in.size()) in1.push_back(in[i++]);
in=in1;
return ;
}
inline void Init(){
n=Read(),q=Read();
ds.Init();
in.push_back(make_pair(1,n));
return ;
}
inline void Solve(){
for(;q;q--){
int opt=Read();
if(opt==1){
int ql=Read(),qr=Read();
int value=Read();
ds.Add(ql,qr,value);
}
if(opt==2){
int ql=Read(),qr=Read();
Print(ds.Query(ql,qr));
}
if(opt==3){
int x=Read();
AddFire(x);
}
if(opt==4){
int ql=Read(),qr=Read();
Clear(ql,qr);
}
WorkFire();
}
return ;
}
#include<ctime>
int main(){
//#define LOCAL
#ifdef LOCAL
int st=clock();
#endif
Init();
Solve();
#ifdef LOCAL
int en=clock();
printf("cost %d ms\n",en-st);
#endif
return 0;
}