LOJ 6278 数列分块入门2
【题解】
分块。块内排序。块内二分出第一个大于等于c的数。
#include<cstdio> #include<algorithm> #include<cmath> #define N 500010 #define rg register using namespace std; int n,m,opt,l,r,c,block,bl[N],tag[N]; struct rec{ int data,pos; }a[N]; inline int read(){ int k=0,f=1; char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); return k*f; } inline bool cmp(rec x,rec y){return x.data<y.data;} inline int find(int pos,int x){ int l=(pos-1)*block+1,r=pos*block, ll=l; while(l<r){ int mid=(l+r+1)>>1; if(a[mid].data<x) l=mid; else r=mid-1; } if(a[l].data>=x) return 0; return l-ll+1; } int main(){ n=read(); block=sqrt(n); for(rg int i=1;i<=n;i++) a[i].data=read(),a[i].pos=i; for(rg int i=1;i<=n;i++) bl[i]=(i-1)/block+1; for(rg int i=1;i<=block+1;i++) sort(a+(i-1)*block+1,a+min(i*block,n)+1,cmp); for(rg int j=1;j<=n;j++){ if((opt=read())==0){ l=read(); r=read(); c=read(); int st=bl[l]+1,ed=bl[r]-1; for(rg int i=st;i<=ed;i++) tag[i]+=c; if(bl[l]==bl[r]){ int x=(bl[l]-1)*block+1,y=min(bl[l]*block,n); for(rg int i=x;i<=y;i++) if(a[i].pos>=l&&a[i].pos<=r) a[i].data+=c; sort(a+x,a+y+1,cmp); continue; } int x=(bl[l]-1)*block+1,y=min(bl[l]*block,n); for(rg int i=x;i<=y;i++) if(a[i].pos>=l) a[i].data+=c; sort(a+x,a+y+1,cmp); x=(bl[r]-1)*block+1,y=min(bl[r]*block,n); for(rg int i=x;i<=y;i++) if(a[i].pos<=r) a[i].data+=c; sort(a+x,a+y+1,cmp); } else{ l=read(); r=read(); c=read(); c*=c; int st=bl[l]+1,ed=bl[r]-1,ans=0; for(rg int i=st;i<=ed;i++) ans+=find(i,c-tag[i]); if(bl[l]==bl[r]){ for(rg int i=(bl[l]-1)*block+1;i<=bl[l]*block;i++) if(a[i].pos>=l&&a[i].pos<=r&&a[i].data+tag[bl[l]]<c) ans++; printf("%d\n",ans); continue; } int x=(bl[l]-1)*block+1,y=min(bl[l]*block,n); for(rg int i=x;i<=y;i++) if(a[i].pos>=l&&a[i].data+tag[bl[l]]<c) ans++; x=(bl[r]-1)*block+1,y=min(bl[r]*block,n); for(rg int i=x;i<=y;i++) if(a[i].pos<=r&&a[i].data+tag[bl[r]]<c) ans++; printf("%d\n",ans); } } return 0; }