poj 2104 主席樹板子題
阿新 • • 發佈:2018-11-15
講真這道題我感覺可以暴力
本篇部落格的意思是讓我們理解一下主席樹板子的具體實現細節
給予那些看懂了思路但是看不懂板子的人的一條小道
。。。其實就是主席樹亂講。。。。
表打我這個蒟蒻 > <
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100005; struct node { int L,R; int sum; }tree[maxn*20]; struct Value { int x; int id; }value[maxn]; bool cmp(Value a,Value b) { return a.x<b.x; } int root[maxn]; int rank[maxn]; int cnt; void updata(int &rt,int num,int l,int r) { tree[cnt++]=tree[rt];//copy 如果rt是根節點 那麼將上一個根節點的元素複製一份(main函式中的root‘i’=root‘i-1’) 在本根節點再做更新 rt=cnt-1; /* 類似於: tree[cnt]=tree[rt];cnt作為新節點 複製的內容是上一級線段樹的同一位置的內容 其實上面也是這個意思 只是我tm懶得刪 rt=cnt; cnt++; */ tree[rt].sum++; if(r==l) return; int mid=(l+r)>>1; if(num<=mid) updata(tree[rt].L,num,l,mid); else updata(tree[rt].R,num,mid+1,r); } int query(int i,int j,int k,int l,int r) { int mid=(l+r)>>1; int left_sum=tree[tree[j].L].sum-tree[tree[i].L].sum;//區間左邊元素個數 if(l==r) return l; if(k<=left_sum) return query(tree[i].L,tree[j].L,k,l,mid);//當左邊元素個數多於k個 那第k小的就在左邊 else return query(tree[i].R,tree[j].R,k-left_sum,mid+1,r); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&value[i].x); value[i].id=i; } sort(value+1,value+1+n,cmp); for(int i=1;i<=n;i++) { rank[value[i].id]=i; } cnt=1; root[0]=0; tree[0].L=tree[0].R=tree[0].sum=0; for(int i=1;i<=n;i++) { root[i]=root[i-1]; updata(root[i],rank[i],1,n); } for(int i=1;i<=m;i++) { int x,y,k; scanf("%d%d%d",&x,&y,&k); int ans=value[query(root[x-1],root[y],k,1,n)].x; printf("%d\n",ans); } }