分块
写到一半的博客突然消失QAQ
心态爆炸
所以我们直接上例题吧
原理有空一定补上
用啥线段树
用分块可以轻松水过
上代码
#include<bits/stdc++.h> using namespace std; namespace _mzf { #define ll long long const ll N=2e6+100; ll n,m,sq,q[N],cnt[N],sum[N]; ll a[N]; ll read() { ll sum=0,flag=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') flag=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { sum=sum*10+ch-'0'; ch=getchar(); } return flag*sum; } void update(ll l,ll r,ll k) { ll ans=0; for(int i=l;i<=min(q[l]*sq,r);i++) { a[i]+=k; sum[q[i]]+=k; } if(q[l]!=q[r]) { for(int i=(q[r]-1)*sq+1;i<=r;i++) { a[i]+=k; sum[q[i]]+=k; } } for(int i=q[l]+1;i<q[r];i++) { cnt[i]+=k; sum[i]+=k*sq; } } ll query(ll l,ll r) { ll ans=0; for(int i=l;i<=min(q[l]*sq,r);i++)ans+=a[i]+cnt[q[i]]; if(q[l]!=q[r]) for(int i=(q[r]-1)*sq+1;i<=r;i++)ans+=a[i]+cnt[q[i]]; for(int i=q[l]+1;i<q[r];i++) ans+=sum[i]; return ans; } void mzfmain() { n=read(); m=read(); sq=sqrt(n); for(int i=1;i<=n;i++) { q[i]=(i-1)/sq+1; a[i]=read(); sum[q[i]]+=a[i]; } while(m--) { ll op,x,y,k; op=read(); if(op==1) { x=read(); y=read(); k=read(); update(x,y,k); } else { x=read(); y=read(); printf("%lld\n",query(x,y)); } } } } int main() { _mzf::mzfmain(); return 0; }
二、超级大水题
板子题
几乎是直接把上面的代码粘过来就能过
代码就不放了(太难看)
三、开关
用啥线段树
分块轻松吊打(大部分)线段树
每个灯都只有0,1两个状态
仍然是散块直接暴力修改+整块修改打标记
开关灯操作怎么办?当然是位运算。
取反?异或更方便!
tag数组异或1可以很方便的标记元素被反转多少次
最后询问的时候异或上即可
然后你就做完了
#include<bits/stdc++.h> using namespace std; namespace _mzf { #define ll long long const ll N=2e5+100; ll sq,n,m,q[N],cnt[N],sum[N],a[N]; ll read() { ll sum=0,flag=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') flag=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { sum=sum*10+ch-'0'; ch=getchar(); } return flag*sum; } void update(ll l,ll r) { for(int i=l;i<=min(q[l]*sq,r);i++) { sum[q[l]]-=(a[i]^cnt[q[l]]); a[i]^=1; sum[q[l]]+=(a[i]^cnt[q[l]]); } if(q[l]!=q[r]) for(int i=(q[r]-1)*sq+1;i<=r;i++) { sum[q[r]]-=(a[i]^cnt[q[r]]); a[i]^=1; sum[q[r]]+=(a[i]^cnt[q[r]]); } for(int i=q[l]+1;i<q[r];i++) { sum[i]=sq-sum[i]; cnt[i]^=1; } } ll query(ll l,ll r) { ll ans=0; for(int i=l;i<=min(q[l]*sq,r);i++) ans+=(a[i]^cnt[q[l]]); if(q[l]!=q[r]) for(int i=(q[r]-1)*sq+1;i<=r;i++) ans+=(a[i]^cnt[q[r]]); for(int i=q[l]+1;i<q[r];i++) ans+=sum[i]; return ans; } void mzfmain() { n=read(); m=read(); sq=sqrt(n); for(int i=1;i<=n;i++) q[i]=(i-1)/sq+1; for(int i=1;i<=m;i++) { ll a,b,c; c=read(); if(!c) { a=read(); b=read(); update(a,b); } else { a=read(); b=read(); cout<<query(a,b)<<endl; } } } } int main() { _mzf::mzfmain(); return 0; }