bzoj5037 线段树练习4加强版(暴力分块)
Posted Sakits
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj5037 线段树练习4加强版(暴力分块)相关的知识,希望对你有一定的参考价值。
求大爷教线段树怎么写啊QAQ
只会写分块...一开始脑抽写成了O(NKlogN)还被CZL大爷嘲讽了一发T T
f[i][j]表示在第i块中,模k为j的数有几个,然后每次修改的时候只需要打个标记,查询的时候直接加上标记查就行了
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int maxn=200010; int n,m,k,blo,x,y,z; int a[maxn],bl[maxn],blcnt[510][maxn],bl2[maxn],bltag[maxn],bltag2[maxn]; char s[233]; inline void read(int &k) { int f=1;k=0;char c=getchar(); while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar(); k*=f; } #define update(x) x>=k&&(x-=k) inline void change(int x,const int &delta) { int now=a[x]; blcnt[bl[x]][now]--; now+=delta;update(now); blcnt[bl[x]][now]++; a[x]+=delta;update(a[x]); } inline void add(int l,int r,const int &delta) { for(int i=l;i<=min(r,bl[l]*blo);i++)change(i,delta); if(bl[l]!=bl[r])for(int i=(bl[r]-1)*blo+1;i<=r;i++)change(i,delta); for(int i=bl[l]+1;i<bl[r];i++) { bltag[i]+=delta;update(bltag[i]); bltag2[i]-=delta;bltag2[i]<0&&(bltag2[i]+=k); } } inline int min(int a,int b){return a<b?a:b;} int query(int l,int r) { int ans=0,tmp,mn=min(bl[l]*blo,r); for(int i=l;i<=mn;i++) ans+=((tmp=a[i]+bltag[bl[i]])==k||!tmp); if(bl[l]!=bl[r])for(int i=(bl[r]-1)*blo+1;i<=r;i++) ans+=((tmp=a[i]+bltag[bl[i]])==k||!tmp); for(int i=bl[l]+1;i<bl[r];i++)ans+=blcnt[i][bltag2[i]]; return ans; } int main() { read(n);read(m);read(k);blo=sqrt(n); for(int i=1;i<=n;i++)bl[i]=(i-1)/blo+1; for(int i=1;i<=n;i++)read(x),a[i]=x%k; for(int i=1;i<=n;i++)blcnt[bl[i]][a[i]]++; for(int i=1;i<=m;i++) { scanf("%s",s);read(x);read(y); if(s[0]==‘a‘) { read(z);z%=k; z<0&&(z+=k); add(x,y,z); } else printf("%d\n",query(x,y)); } }
以上是关于bzoj5037 线段树练习4加强版(暴力分块)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 3514 Codechef MARCH14 GERALD07加强版 Link-Cut-Tree+划分树