【BZOJ 3196】 Tyvj 1730 二逼平衡树 分块
分块 就是分块嘛!
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cstdlib> #include <cmath> #define MAXN 1000000 #define INF 1000000000 #define MO 233333333 #define LL long long using namespace std; int num[300][300]; int init[50000+1]; int n,m; int cnt,lenth; int Find(int tmp[300],int k) { int L=1,R=tmp[0]; while(L<R) { int mid=(L+R)/2; if(tmp[mid]>=k) R=mid; else L=mid+1; } if(tmp[L]>=k)return L-1; return L; } int Rank(int L,int R,int k) { int ans=0; int s=(L+lenth-1)/lenth,t=(R+lenth-1)/lenth;// cout<<lenth<<endl; if(s!=t) { for(int i=L;i<=lenth*s;i++) if(init[i]<k) ans++; s++; for(int i=R;i>=lenth*(t-1)+1;i--) if(init[i]<k) ans++; for(int i=s;i<t;i++) ans+=Find(num[i],k); } else { for(int i=L;i<=R;i++) if(init[i]<k) ans++; } return ans+1; } int Kth(int L,int R,int k) { int s=0,t=100000000; int ans=0; while(s<t) { int mid=(s+t)/2; if(Rank(L,R,mid)>k) t=mid; else s=mid+1,ans=mid; } return ans; } void Change(int loc,int k) { init[loc]=k; int tmp=(loc+lenth-1)/lenth; for(int i=1;i<=num[tmp][0];i++) num[tmp][i]=init[(tmp-1)*lenth+i]; sort(num[tmp]+1,num[tmp]+num[tmp][0]+1); } int Before(int L,int R,int k) { int s=(L+lenth-1)/lenth,t=(R+lenth-1)/lenth; int mmax=-1;//cout<<s<<' '<<t<<endl; if(s!=t) { for(int i=L;i<=s*lenth;i++) if(init[i]<k) mmax=max(mmax,init[i]); s++; for(int i=R;i>=(s-1)*lenth;i--) if(init[i]<k) mmax=max(mmax,init[i]); for(int i=s;i<t;i++) { int x=Find(num[i],k); if(x!=0) mmax=max(num[i][x],mmax); } } else { for(int i=L;i<=R;i++) if(init[i]<k) mmax=max(mmax,init[i]); } return mmax; } int Find_After(int tmp[300],int k) { int L=1,R=tmp[0]; while(L<R) { int mid=(L+R)/2; if(tmp[mid+1]<=k) L=mid+1; else R=mid; } if(tmp[L]<=k) return L+1; return L; } int After(int L,int R,int k) { int s=(L+lenth-1)/lenth,t=(R+lenth-1)/lenth; int mmin=100000000+1; if(s!=t) { for(int i=L;i<=s*lenth;i++) if(init[i]>k) mmin=min(mmin,init[i]); s++; for(int i=R;i>=(s-1)*lenth;i--) if(init[i]>k) mmin=min(mmin,init[i]); for(int i=s;i<t;i++) { int x=Find_After(num[i],k); if(x!=num[i][0]+1) mmin=min(num[i][x],mmin); } } else { for(int i=L;i<=R;i++) if(init[i]>k) mmin=min(mmin,init[i]); } return mmin; } int main() { // freopen("a.in","r",stdin); cin>>n>>m; //cout<<n<<endl; for(int i=1;i<=n;i++) scanf("%d",&init[i]); lenth=sqrt(n)+2; cnt=lenth; for(int i=1;i<=cnt;i++) { for(int j=1;j<=lenth;j++) num[i][j]=init[(i-1)*lenth+j]; sort(num[i]+1,num[i]+lenth+1); num[i][0]=lenth; } if(n%lenth!=0) { cnt++; num[cnt][0]=n%lenth; for(int i=1;i<=num[cnt][0];i++) num[cnt][i]=init[(cnt-1)*lenth+i]; sort(num[cnt]+1,num[cnt]+1+num[cnt][0]); } int L,R,pos,opt,k; for(int i=1;i<=m;i++) { scanf("%d",&opt); switch (opt) { case 1: { scanf("%d %d %d",&L,&R,&k); printf("%d\n",Rank(L,R,k)); break; } case 2: { scanf("%d %d %d",&L,&R,&k); printf("%d\n",Kth(L,R,k)); break; } case 3: { scanf("%d %d",&pos,&k); Change(pos,k); break; } case 4: { scanf("%d %d %d",&L,&R,&k); printf("%d\n",Before(L,R,k)); break; } case 5: { scanf("%d %d %d",&L,&R,&k); printf("%d\n",After(L,R,k)); break; } } } return 0; }