[BZOJ 1901]Dynamic Rankings
终于A了!
做了4个月了,终于A了!
这个题其实不难。只要用树状数组维护主席树即可。不过请注意,此题的实际数据范围远比10000大!
代码:
/************************************************************** Problem: 1901 User: danihao123 Language: C++ Result: Accepted Time:540 ms Memory:32712 kb ****************************************************************/ #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int maxn=120051; const int maxlogn=31; const int maxnode=maxn*20; // ChairTree int sumv[maxnode]; int lc[maxnode],rc[maxnode]; int ct_cnt=0; int build_tree(int L,int R){ int ans=++ct_cnt; if(R>L){ int M=L+(R-L)/2; lc[ans]=build_tree(L,M); rc[ans]=build_tree(M+1,R); } return ans; } int p,v; int update(int o,int L,int R){ int ans=++ct_cnt; sumv[ans]=sumv[o]; lc[ans]=lc[o]; rc[ans]=rc[o]; if(R>L){ int M=L+(R-L)/2; if(p<=M) lc[ans]=update(lc[ans],L,M); else rc[ans]=update(rc[ans],M+1,R); } sumv[ans]+=v; return ans; } int LT_siz,RT_siz; int LT[maxlogn],RT[maxlogn]; int query(int L,int R,int k){ if(L==R) return L; int i; int LT_ans=0,RT_ans=0,the_ans,M=L+(R-L)/2; for(i=1;i<=LT_siz;i++) LT_ans+=sumv[lc[LT[i]]]; for(i=1;i<=RT_siz;i++) RT_ans+=sumv[lc[RT[i]]]; the_ans=RT_ans-LT_ans; if(k<=the_ans){ for(i=1;i<=LT_siz;i++) LT[i]=lc[LT[i]]; for(i=1;i<=RT_siz;i++) RT[i]=lc[RT[i]]; return query(L,M,k); }else{ for(i=1;i<=LT_siz;i++) LT[i]=rc[LT[i]]; for(i=1;i<=RT_siz;i++) RT[i]=rc[RT[i]]; return query(M+1,R,k-the_ans); } } int rt[maxn]; int siz; inline int lowbit(int x){ return x&(-x); } int n; void change(int pos,int value,int delta){ p=value; v=delta; while(pos<=n){ rt[pos]=update(rt[pos],1,siz); pos+=lowbit(pos); } } int get_ans(int l,int r,int k){ int temp=l-1; LT_siz=RT_siz=0; while(temp>0){ LT[++LT_siz]=rt[temp]; temp-=lowbit(temp); } while(r>0){ RT[++RT_siz]=rt[r]; r-=lowbit(r); } return query(1,siz,k); } int pre[maxn]; int A[maxn],A2[maxn]; int real_siz=0; void init_CT(){ register int i,pos; sort(A2+1,A2+1+real_siz); siz=unique(A2+1,A2+1+real_siz)-A2-1; rt[0]=build_tree(1,siz); for(i=1;i<=n;i++) rt[i]=rt[0]; for(i=1;i<=n;i++){ pos=lower_bound(A2+1,A2+1+siz,pre[i])-A2; change(i,pos,1); } } inline int get_lsh(int x){ return lower_bound(A2+1,A2+1+siz,x)-A2; } int Query[maxn][4]; int main(){ int m,u,v,d; char buf[3]; register int i; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",&pre[i]); A2[++real_siz]=pre[i]; } for(i=1;i<=m;i++){ scanf("%s%d%d",buf,&u,&v); Query[i][1]=u; Query[i][2]=v; if(buf[0]=='C'){ Query[i][0]=1; A2[++real_siz]=v; }else{ Query[i][0]=0; scanf("%d",&Query[i][3]); } } init_CT(); for(i=1;i<=m;i++){ if(Query[i][0]){ change(Query[i][1],get_lsh(pre[Query[i][1]]),-1); pre[Query[i][1]]=Query[i][2]; change(Query[i][1],get_lsh(Query[i][2]),1); }else{ printf("%d\n",A2[get_ans(Query[i][1],Query[i][2],Query[i][3])]); } } return 0; }
[POJ 2104]K-th Number
我擦终于A了这题了!
主席树坑点多……
最好不要写指针主席树,不然容易TLE……(自带常数?)
并且注意,一定要把数组开大,开大,再开大,重要的事情说三遍
代码: