CODEVS.5037.线段树练习4加强版(分块 区间k的倍数)
生活随笔
收集整理的這篇文章主要介紹了
CODEVS.5037.线段树练习4加强版(分块 区间k的倍数)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
/* 如果用線段樹,每個節點要再開k的空間,顯然不行。但是分塊可以(雖然空間依舊爆炸)分塊。用bloans[i][j]表示 第i塊 模k為j 的有多少個 對于不是整塊的,查詢時應判斷 A[i]+tag[belong[i]] ==k || ==0 對于整塊,維護兩個tag,一個是整塊的加標記,另一個是整塊的mod數標記tag2,初始時tag2為0 當整塊+v時,tag2 -=v。因為查詢的應是 模k=0 的數的個數,整塊+v后,這塊要查的就是 模k=k-v ((k-v+v)%k=0)的個數 這樣就很巧妙地將整塊加變成了改詢問 */ #include<cmath> #include<cstdio> #include<cctype> #include<algorithm> using namespace std; const int N=2e5+5,MAXSZ=460;int n,m,k,size,A[N],belong[N],bloans[MAXSZ][N],tag[MAXSZ],tag2[MAXSZ];inline int read() {int now=0,f=1;register char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-') f=-1;for(;isdigit(c);now=now*10+c-'0',c=getchar());return now*f; }void Update(int p,int v) {--bloans[belong[p]][A[p]];A[p]+=v;if(A[p]>=k) A[p]-=k;++bloans[belong[p]][A[p]]; } void Add(int l,int r,int v) {int t=min(r,belong[l]*size);for(int i=l; i<=t; ++i)Update(i,v);if(belong[l]!=belong[r])for(int i=(belong[r]-1)*size+1; i<=r; ++i)Update(i,v);for(int i=belong[l]+1; i<belong[r]; ++i){tag[i]+=v, tag2[i]-=v;if(tag[i]>=k) tag[i]-=k;if(tag2[i]<0) tag2[i]+=k;} } int Query(int l,int r) {int res=0, t=min(r,belong[l]*size);for(int i=l; i<=t; ++i)if(A[i]+tag[belong[l]]==k || !(A[i]+tag[belong[l]]))++res;if(belong[l]!=belong[r])for(int i=(belong[r]-1)*size+1; i<=r; ++i)if(A[i]+tag[belong[r]]==k || !(A[i]+tag[belong[r]]))//beblong[l] belong[r]別寫反了 ++res;for(int i=belong[l]+1; i<belong[r]; ++i)res+=bloans[i][tag2[i]];return res; }int main() {n=read(),m=read(),k=read();size=sqrt(n);for(int i=1;i<=n;++i){A[i]=read()%k, belong[i]=(i-1)/size+1;if(A[i]<0) A[i]+=k;++bloans[belong[i]][A[i]];}char opt[9];int l,r,v;while(m--){scanf("%s",opt);l=read(),r=read();if(opt[0]=='a')v=read(), Add(l,r,(v%k+k)%k);elseprintf("%d\n",Query(l,r));}return 0; }轉載于:https://www.cnblogs.com/SovietPower/p/8435078.html
總結
以上是生活随笔為你收集整理的CODEVS.5037.线段树练习4加强版(分块 区间k的倍数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Angular——单页面与路由的使用
- 下一篇: elasticsearch索引和映射