zoj2112
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112
经典的动态区间第K大。
用树状数组套线段树。
对原数组建一个树状数组,每个树状数组的结点代表一个线段树,这个线段树以权值为下标,包括这个树状数组的结点包含的区间。
插入的时候可以由树状数组和线段树写法类比,只与logn棵线段树有关,每棵线段树用时logn,总共的时间复杂度n*logn^2。
询问[l,r]的时候,类似与前缀和,找到与l-1有关的logn棵线段树,找到与人有关的logn棵线段树,然后类似于静态区间第K大,判断是往左子树还是右子树,有2logn棵线段树,判断往左子树还是右子树logn次,总共的时间复杂度n*logn^2。
网址上空间比较小,这个程序会MLE。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); inline int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } inline LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxN=50000; const int maxM=10000; const int maxcnt=maxN+maxM; int N,M; int a[maxN+100]; struct Tdata { char type; int l,r,k,t; inline void input() { type=getchar();while(!(type=='C' || type=='Q'))type=getchar(); if(type=='Q'){l=gint();r=gint();k=gint();}else{l=gint();t=gint();} } }data[maxM+100]; int bak[maxcnt+100],cnt; struct Tnode{int son[2],val;}sn[maxcnt*100+10000];int idx; int tree[maxN+100]; inline int newnode(){++idx;sn[idx].son[0]=sn[idx].son[1]=sn[idx].val=0;return idx;} inline void update(int p,int l,int r,int x,int val) { while(1) { sn[p].val+=val; if(l==r)break; int mid=(l+r)/2; int f=(x>mid); if(!sn[p].son[f])sn[p].son[f]=newnode(); if(x<=mid){p=sn[p].son[0];r=mid;}else{p=sn[p].son[1];l=mid+1;} } } #define lowbit(a) (a&(-a)) inline void change(int a,int x,int val) { for(;a<=N;a+=lowbit(a)) update(tree[a],1,cnt,x,val); } int lge,larr[maxN+100],rge,rarr[maxN+100]; inline int ask(int l,int r,int k) { int i; l--; lge=0; for(;l>=1;l-=lowbit(l))larr[++lge]=tree[l]; rge=0; for(;r>=1;r-=lowbit(r))rarr[++rge]=tree[r]; int x=1,y=cnt; while(1) { if(x==y)return bak[x]; int mid=(x+y)/2,G=0; re(i,1,rge)G+=sn[sn[rarr[i]].son[0]].val; re(i,1,lge)G-=sn[sn[larr[i]].son[0]].val; if(G<k) { k-=G; x=mid+1; re(i,1,rge)rarr[i]=sn[rarr[i]].son[1]; re(i,1,lge)larr[i]=sn[larr[i]].son[1]; } else { y=mid; re(i,1,rge)rarr[i]=sn[rarr[i]].son[0]; re(i,1,lge)larr[i]=sn[larr[i]].son[0]; } } } int main() { freopen("zoj2112.in","r",stdin); freopen("zoj2112.out","w",stdout); int i; for(int Case=gint();Case;Case--) { N=gint();M=gint(); re(i,1,N)a[i]=gint(); re(i,1,M)data[i].input(); cnt=0; re(i,1,N)bak[++cnt]=a[i]; re(i,1,M)if(data[i].type=='C')bak[++cnt]=data[i].t; sort(bak+1,bak+cnt+1); cnt=unique(bak+1,bak+cnt+1)-bak-1; re(i,1,N)a[i]=lower_bound(bak+1,bak+cnt+1,a[i])-bak; re(i,1,M)if(data[i].type=='C')data[i].t=lower_bound(bak+1,bak+cnt+1,data[i].t)-bak; idx=0; re(i,0,N)tree[i]=newnode(); re(i,1,N)change(i,a[i],1); re(i,1,M) { int x; switch(data[i].type) { case 'C': x=data[i].l; change(x,a[x],-1); a[x]=data[i].t; change(x,a[x],1); break; case 'Q': printf("%d\n",ask(data[i].l,data[i].r,data[i].k)); break; } } } return 0; }