poj-2104(区间第K大问题)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 struct T { 7 int ls; 8 int rs; 9 int sum; 10 }; 11 const int N=1e5+7; 12 T tri[40*N]; 13 int a[N],sort_a[N]; 14 int rt[N]; 15 int cnt; 16 int n,m; 17 void update (int l,int r,int rt1,int &rt2,int pos) { 18 rt2=++cnt; 19 tri[rt2]=tri[rt1]; 20 tri[rt2].sum++;// 在此处直接更新,就不用pushup了 21 if (l==r) return ; 22 int mid=(l+r)/2; 23 if (pos<=mid) update (l,mid,tri[rt1].ls,tri[rt2].ls,pos); 24 else update (mid+1,r,tri[rt1].rs,tri[rt2].rs,pos); 25 return ; 26 } 27 int query (int l,int r,int rt1,int rt2,int k) { 28 if (l==r) return sort_a[l]; 29 int mid=(l+r)/2; 30 int sum=tri[tri[rt2].ls].sum-tri[tri[rt1].ls].sum;//我又出错了 sum应该是左子树的节点数 T_T ! 31 if (k<=sum) return query (l,mid,tri[rt1].ls,tri[rt2].ls,k); 32 else return query (mid+1,r,tri[rt1].rs,tri[rt2].rs,k-sum); 33 } 34 int main () 35 { 36 scanf ("%d %d",&n,&m); 37 for (int i=1;i<=n;i++) { 38 scanf ("%d",&a[i]); 39 sort_a[i]=a[i]; 40 } 41 sort (sort_a+1,sort_a+1+n); 42 int num=1; 43 for (int i=2;i<=n;i++) { 44 if (sort_a[i]!=sort_a[i-1]) 45 sort_a[++num]=sort_a[i];//离散化 46 } 47 rt[0]=cnt=0; 48 tri[0].sum=tri[0].ls=tri[0].rs=0; 49 for (int i=1;i<=n;i++) { 50 int pos=lower_bound (sort_a+1,sort_a+1+num,a[i])-sort_a; 51 update (1,num,rt[i-1],rt[i],pos); 52 } 53 for (int i=1;i<=m;i++) { 54 int x,y,k; 55 scanf ("%d %d %d",&x,&y,&k); 56 printf("%d ",query (1,num,rt[x-1],rt[y],k)); 57 } 58 return 0; 59 }
NO.2 HDOJ-4417(主席数的区间求和)
1 #include<cstdio> 2 #include<algorithm> 3 const int N=1e5+7; 4 using namespace std; 5 struct node { 6 int ls; 7 int rs; 8 int sum; 9 }; 10 node tri[40*N]; 11 int rt[N]; 12 int a[N],sort_a[N+1]; 13 int cnt,n,m,x,y,k; 14 void updata (int l,int r,int rt1,int& rt2,int pos) { 15 rt2=(++cnt); 16 tri[rt2]=tri[rt1]; 17 tri[rt2].sum++; 18 if (l==r) return ; 19 int mid=(l+r)/2; 20 if (pos<=mid) updata(l,mid,tri[rt1].ls,tri[rt2].ls,pos); 21 else updata(mid+1,r,tri[rt1].rs,tri[rt2].rs,pos); 22 return ; 23 } 24 int query (int l,int r,int L,int R,int rt1,int rt2) { 25 if (r<L||l>R) return 0; 26 if (l>=L&&r<=R) return tri[rt2].sum-tri[rt1].sum; 27 int mid=(l+r)/2; 28 int t1=query(l,mid,L,R,tri[rt1].ls,tri[rt2].ls); 29 int t2=query(mid+1,r,L,R,tri[rt1].rs,tri[rt2].rs); 30 return t1+t2; 31 } 32 int main () 33 { 34 int T; 35 int tt=1; 36 scanf ("%d",&T); 37 while (T--) { 38 printf("Case %d: ",tt++); 39 scanf ("%d %d",&n,&m); 40 for (int i=1;i<=n;i++) { 41 scanf ("%d",&a[i]); 42 sort_a[i]=a[i]; 43 } 44 sort(sort_a+1,sort_a+1+n); 45 int num=1; 46 for (int i=2;i<=n;i++) { 47 if (sort_a[i]!=sort_a[num]) 48 sort_a[++num]=sort_a[i]; 49 } 50 cnt=0; 51 rt[0]=0; 52 tri[0].ls=tri[0].rs=tri[0].sum=0; 53 for (int i=1;i<=n;i++) { 54 int pos=lower_bound(sort_a+1,sort_a+1+num,a[i])-sort_a; 55 updata(1,num,rt[i-1],rt[i],pos); 56 } 57 for (int i=1;i<=m;i++) { 58 scanf ("%d %d %d",&x,&y,&k); 59 int t=lower_bound(sort_a+1,sort_a+1+num,k)-sort_a; 60 if (t>num||sort_a[t]>k) t--;// 这个好 找最后一个小于等于k的数 61 int ans=query (1,num,1,t,rt[x],rt[y+1]);// 因为题目从0开始计数 62 printf("%d ",ans); 63 } 64 } 65 return 0; 66 }
No.3 xdoj-1216(子树第k小)——dfs+主席树
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 using namespace std; 5 const int N=1e5+7; 6 struct T{ 7 int ls; 8 int rs; 9 int sum; 10 }; 11 vector < vector <int> > g(N); 12 T tri[N*40]; 13 int rt[N],b[N],sort_b[N]; 14 int in[N],out[N]; 15 int val[N]; 16 int cnt,num; 17 int n,q; 18 int x,k; 19 void dfs (int id,int pre) { 20 num++; 21 sort_b[num]=b[num]=val[id]; 22 in[id]=num; 23 for (int i=0;i<g[id].size();i++) { 24 int next=g[id][i]; 25 if (next==pre) continue; 26 dfs (next,id); 27 } 28 out[id]=num; 29 } 30 void updata (int l,int r,int pos,int rt1,int& rt2) { 31 cnt++; 32 rt2=cnt; 33 tri[cnt]=tri[rt1]; 34 tri[cnt].sum++; 35 if (l==r) return ; 36 int mid=(l+r)/2; 37 if (pos<=mid) updata (l,mid,pos,tri[rt1].ls,tri[rt2].ls); 38 else updata (mid+1,r,pos,tri[rt1].rs,tri[rt2].rs); 39 return ; 40 } 41 int query (int l,int r,int k,int rt1,int rt2) { 42 if (l==r) return l; 43 int mid=(l+r)/2; 44 int ans; 45 int sum=tri[tri[rt2].ls].sum-tri[tri[rt1].ls].sum; 46 if (k<=sum) ans=query (l,mid,k,tri[rt1].ls,tri[rt2].ls); 47 else ans=query (mid+1,r,k-sum,tri[rt1].rs,tri[rt2].rs); 48 return ans; 49 } 50 int main () 51 { 52 while (scanf ("%d",&n)!=EOF) { 53 for (int i=1;i<=n;i++) g[i].clear(); 54 for (int i=1;i<=n;i++) 55 scanf ("%d",&val[i]); 56 int u,v; 57 for (int i=1;i<=n-1;i++) { 58 scanf ("%d %d",&u,&v); 59 g[u].push_back(v); 60 g[v].push_back(u); 61 } 62 num=0; 63 dfs (1,-1);// 按理说有根树 直接dfs(1)就可以了可是这样答案是不对的 是我理解错了还是数据有问题呢 64 sort(sort_b+1,sort_b+1+n); 65 int nn=1; 66 for (int i=2;i<=n;i++) 67 if (sort_b[i]!=sort_b[nn]) 68 sort_b[++nn]=sort_b[i]; 69 rt[0]=0; 70 tri[0].rs=tri[0].ls=tri[0].sum=0; 71 cnt=0; 72 for (int i=1;i<=n;i++) { 73 int pos=lower_bound(sort_b+1,sort_b+1+nn,b[i])-sort_b; 74 updata(1,nn,pos,rt[i-1],rt[i]); 75 } 76 scanf ("%d",&q); 77 for (int i=1;i<=q;i++) { 78 scanf ("%d %d",&x,&k); 79 int ans=query (1,nn,k,rt[in[x]-1],rt[out[x]]); 80 printf ("%d ",sort_b[ans]); 81 } 82 } 83 return 0; 84 }