zoj - 2112 带修改主席树 + 空间优化
生活随笔
收集整理的這篇文章主要介紹了
zoj - 2112 带修改主席树 + 空间优化
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
ZOJ - 2112
題意:求區間第k小
思路:帶修改區間第k小裸題,無修改的主席樹是維護一個前綴線段樹,每次更新log個節點,用root 和 ls rs作為每顆前綴線段樹的根節點和左右子樹的索引(相當于指針),帶修改的主席樹是也是維護前綴線段樹,不過是用樹狀數組維護,思想和樹狀數組維護前綴和一樣,每次向上更新,向下求和;時間和空間復雜度都是(n+q)*logn*logn;但是zoj卡內存,簡直心里陰影,交了近100發才A。。。由于修改比較少內存優化后時間空間復雜度降低到了n*logn+q*logn*logn,但是沒有太理解優化的原理,優化操作是先建一顆靜態主席樹,然后修改操作用另一個S數組索代替root引根節點
AC代碼:
#include "iostream" #include "iomanip" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a,x) memset(a,x,sizeof(a)) #define step(x) fixed<< setprecision(x)<< #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define ll long long #define endl ("\n") #define ft first #define sd second #define lrt (rt<<1) #define rrt (rt<<1|1) using namespace std; const ll mod=1e9+7; const ll INF = 1e18+1LL; const int inf = 1e9+1e8; const double PI=acos(-1.0); const int N=6e4+100;int sum[32*N],ls[32*N],rs[32*N],root[N],S[N],cnt; int n,m,sz,tk[N],a[N]; void creat(int &cur, int l, int r){cur=++cnt;sum[cur]=0;if(l==r) return;int mid=l+r>>1;creat(ls[cur],l,mid);creat(rs[cur],mid+1, r); }void update(int &cur, int l, int r, int p, int last, int u){cur=++cnt;ls[cur]=ls[last];rs[cur]=rs[last];sum[cur]=sum[last]+u;if(l==r) return;int mid=l+r>>1;if(p<=mid) update(ls[cur], l, mid, p, ls[cur], u);else update(rs[cur], mid+1, r, p, rs[cur], u); }int lowbit(int x){return x&(-x); }void add(int x, int p, int u){while(x<=n){update(S[x],1,sz,p,S[x],u);x+=lowbit(x);} }int query(int l, int r, int L, int R, int k){int bit[60010], rtl=root[L], rtr=root[R];for(int i=L; i>0; i-=lowbit(i)) bit[i]=S[i];for(int i=R; i>0; i-=lowbit(i)) bit[i]=S[i];while(l<r){int t=sum[ls[rtr]]-sum[ls[rtl]];for(int i=R; i>0; i-=lowbit(i)) t+=sum[ls[bit[i]]];for(int i=L; i>0; i-=lowbit(i)) t-=sum[ls[bit[i]]];int mid=l+r>>1;if(t>=k){for(int i=L; i>0; i-=lowbit(i)) bit[i]=ls[bit[i]];for(int i=R; i>0; i-=lowbit(i)) bit[i]=ls[bit[i]];rtl=ls[rtl],rtr=ls[rtr],r=mid;}else{for(int i=L; i>0; i-=lowbit(i)) bit[i]=rs[bit[i]];for(int i=R; i>0; i-=lowbit(i)) bit[i]=rs[bit[i]];rtl=rs[rtl],rtr=rs[rtr],l=mid+1; k-=t;}}return l; }struct Qu{char c[4];int l, r, k; }q[10005];void hash_init(){sort(tk+1,tk+1+sz);sz=unique(tk+1,tk+1+sz)-(tk+1); } int _hash(int x){return lower_bound(tk+1,tk+1+sz,x)-tk; } int main(){int T; scanf("%d",&T);while(T--){scanf("%d%d",&n,&m); cnt=0,sz=0;//sz表示線段樹(主席樹)的葉子節點數for(int i=1; i<=n; ++i){scanf("%d",&a[i]);tk[++sz]=a[i];}for(int i=1; i<=m; ++i){scanf("%s",q[i].c);if(q[i].c[0]=='Q'){scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);}else{scanf("%d%d",&q[i].l,&q[i].r);tk[++sz]=q[i].r;}}hash_init();creat(root[0],1,sz);for(int i=1; i<=n; ++i){update(root[i],1,sz,_hash(a[i]),root[i-1],1);}for(int i=1; i<=n; ++i) S[i]=root[0];for(int i=1; i<=m; ++i){if(q[i].c[0]=='Q'){printf("%d\n",tk[query(1, sz, q[i].l-1, q[i].r, q[i].k)] );}else{add(q[i].l, _hash(a[q[i].l]), -1);add(q[i].l, _hash(q[i].r), 1);a[q[i].l]=q[i].r;}}}return 0; }?
轉載于:https://www.cnblogs.com/max88888888/p/7553596.html
總結
以上是生活随笔為你收集整理的zoj - 2112 带修改主席树 + 空间优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java快速寻找一个数组的最大值或最小值
- 下一篇: 关于ESXI能虚拟出多少个虚拟机和CPU