【洛谷p2801】教主的魔法【分塊模板】
阿新 • • 發佈:2018-12-15
給出一個數列,支援區間修改,區間查詢大於等於key的值個數,分塊模板加一個小二分。
詳情見程式碼。A指查詢(L到R大於x),M指修改(將L到R增加x)
#include<bits/stdc++.h> #define in in() using namespace std; int in{ int cnt=0,f=1; char ch=0; while(!isdigit(ch)){ ch=getchar(); if(ch=='-')f=-1; } while(isdigit(ch)){ cnt=cnt*10+ch-48; ch=getchar(); } return cnt*f; } int n,q; int belong[1000003],l[1000003],r[1000003],p[1000003]; int d[1000003]; int a[1000003]; void build(){ int block=sqrt(n); int num=n/block; if(n%block)num++; for(int i=1;i<=n;i++){ belong[i]=(i-1)/block+1; d[i]=a[i]; } for(int i=1;i<=num;i++){ l[i]=(i-1)*block+1; r[i]=i*block; } r[num]=n; for(int i=1;i<=num;i++){ sort(d+l[i],d+r[i]+1); } } void update(int L,int R,int v){ if(belong[L]==belong[R]){ for(int i=L;i<=R;i++){ a[i]+=v; } for(int i=l[belong[L]];i<=r[belong[L]];i++){ d[i]=a[i]; } sort(d+l[belong[L]],d+r[belong[L]]+1); } else{ for(int i=L;i<=r[belong[L]];i++){ a[i]+=v; } for(int i=l[belong[L]];i<=r[belong[L]];i++){ d[i]=a[i]; } sort(d+l[belong[L]],d+r[belong[L]]+1); for(int i=l[belong[R]];i<=R;i++){ a[i]+=v; } for(int i=l[belong[R]];i<=r[belong[R]];i++){ d[i]=a[i]; } sort(d+l[belong[R]],d+r[belong[R]]+1); for(int i=belong[L]+1;i<=belong[R]-1;i++){ p[i]+=v; } } } int query(int L,int R,int v){ int ans=0; if(belong[L]==belong[R]){ for(int i=L;i<=R;i++){ if(a[i]+p[belong[i]]>=v)ans++; } return ans; } for(int i=L;i<=r[belong[L]];i++){ if(a[i]+p[belong[i]]>=v)ans++; } for(int i=l[belong[R]];i<=R;i++){ if(a[i]+p[belong[i]]>=v)ans++; } for(int i=belong[L]+1;i<=belong[R]-1;i++){ int ll=l[i],rr=r[i],mid,result=0;; while(ll<=rr){ mid=(ll+rr)>>1; if(d[mid]+p[i]>=v)rr=mid-1,result=r[i]-mid+1; else ll=mid+1; } ans+=result; } return ans; } int main(){ //freopen("testdata.in","r",stdin); // freopen("1.out","w",stdout); n=in;q=in; for(int i=1;i<=n;i++){ a[i]=in; } build(); int x,y,z;char c[6]; while(q--){ scanf("%s",c);x=in;y=in;z=in; if(c[0]=='A'){ printf("%d\n",query(x,y,z)); } else update(x,y,z); } return 0; }
本程式碼重點在於隨時維護一個d陣列保持其按照每塊塊內升序,這樣在查詢大塊大於時可以用二分確定個數。
程式碼細節很多,一定要記清楚belong對應的意義和l,r對應的意義。