1. 程式人生 > >bzoj 2588 Spoj 10628. Count on a tree (可持久化線段樹)

bzoj 2588 Spoj 10628. Count on a tree (可持久化線段樹)

change lca 權值線段樹 mat sin urn problem sample des

Spoj 10628. Count on a tree

Time Limit: 12 Sec Memory Limit: 128 MB
Submit: 7669 Solved: 1894
[Submit][Status][Discuss]

Description

給定一棵N個節點的樹,每個點有一個權值,對於M個詢問(u,v,k),你需要回答u xor lastans和v這兩個節點間第K小的點權。其中lastans是上一個詢問的答案,初始為0,即第一個詢問的u是明文。

Input

第一行兩個整數N,M。 第二行有N個整數,其中第i個整數表示點i的權值。 後面N-1行每行兩個整數(x,y),表示點x到點y有一條邊。 最後M行每行兩個整數(u,v,k),表示一組詢問。

Output

M行,表示每個詢問的答案。最後一個詢問不輸出換行符

Sample Input

8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2

Sample Output

2
8
9
105
7

HINT




HINT:
N,M<=100000
暴力自重。。。

Source

鳴謝seter

題解,可持久化權值線段樹上二分即可, 很好理解的,我自己寫的runtime了好久,不知道為什麽。
改成hzwer的就過了,GG。 AC代碼
  1 #include<cstring>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstdio>
  6 
  7 #define N 100007
  8 #define M 2000007
  9 using namespace std;
 10 inline int read()
 11 {
 12     int x=0,f=1;char
ch=getchar(); 13 while(ch>9||ch<0){if (ch==-) f=-1;ch=getchar();} 14 while(ch<=9&&ch>=0){x=(x<<3)+(x<<1)+ch-0;ch=getchar();} 15 return x*f; 16 } 17 18 int n,m,top,sz,ind; 19 int a[N],zhi[N]; 20 int num[N],fx[N]; 21 int cnt,head[N],next[2*N],rea[2*N]; 22 int ls[M],rs[M],sum[M],root[N]; 23 int deep[N],fa[N][17]; 24 25 int find(int x) 26 { 27 int l=1,r=top; 28 while(l<=r) 29 { 30 int mid=(l+r)>>1; 31 if (zhi[mid]==x) return mid; 32 if (zhi[mid]<x) l=mid+1; 33 else r=mid-1; 34 } 35 } 36 void add(int u,int v) 37 { 38 next[++cnt]=head[u]; 39 head[u]=cnt; 40 rea[cnt]=v; 41 } 42 void dfs(int u) 43 { 44 ind++,num[ind]=u,fx[u]=ind; 45 for (int i=1;i<=16;i++) 46 fa[u][i]=fa[fa[u][i-1]][i-1]; 47 for (int i=head[u];i!=-1;i=next[i]) 48 { 49 int v=rea[i]; 50 if (fa[u][0]!=v) 51 { 52 deep[v]=deep[u]+1; 53 fa[v][0]=u; 54 dfs(v); 55 } 56 } 57 } 58 int lca(int a,int b) 59 { 60 if (deep[a]<deep[b]) swap(a,b); 61 int i; 62 for (i=0;(1<<i)<=deep[a];i++); 63 i--; 64 for (int j=i;j>=0;j--) 65 if (deep[a]-(1<<j)>=deep[b]) a=fa[a][j]; 66 if (a==b) return a; 67 for (int j=i;j>=0;j--) 68 if (fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j]; 69 return fa[a][0]; 70 } 71 void change(int l,int r,int x,int &y,int z) 72 { 73 y=++sz; 74 sum[y]=sum[x]+1; 75 if (l==r) return; 76 ls[y]=ls[x],rs[y]=rs[x]; 77 int mid=(l+r)>>1; 78 if (z<=mid) change(l,mid,ls[x],ls[y],z); 79 else change(mid+1,r,rs[x],rs[y],z); 80 } 81 int query(int l,int r,int a,int b,int c,int d,int rank) 82 { 83 if (l==r) return zhi[l]; 84 int mid=(l+r)>>1,tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]; 85 if (tmp>=rank) return query(l,mid,ls[a],ls[b],ls[c],ls[d],rank); 86 else return query(mid+1,r,rs[a],rs[b],rs[c],rs[d],rank-tmp); 87 88 } 89 int que(int x,int y,int rk) 90 { 91 int a=x,b=y,c=lca(x,y),d=fa[c][0]; 92 a=root[fx[a]],b=root[fx[b]],c=root[fx[c]],d=root[fx[d]]; 93 int l=1,r=top; 94 while(l<r) 95 { 96 int mid=(l+r)>>1; 97 int tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]; 98 if(tmp>=rk)r=mid,a=ls[a],b=ls[b],c=ls[c],d=ls[d]; 99 else rk-=tmp,l=mid+1,a=rs[a],b=rs[b],c=rs[c],d=rs[d]; 100 } 101 return zhi[l]; 102 } 103 int main() 104 { 105 memset(head,-1,sizeof(head)); 106 n=read(),m=read(); 107 for (int i=1;i<=n;i++) 108 a[i]=read(),zhi[i]=a[i]; 109 sort(zhi+1,zhi+n+1); 110 top=1; 111 for (int i=2;i<=n;i++) 112 if (zhi[i]!=zhi[i-1]) zhi[++top]=zhi[i]; 113 for (int i=1;i<=n;i++) 114 a[i]=find(a[i]); 115 for (int i=1;i<n;i++) 116 { 117 int x=read(),y=read(); 118 add(x,y),add(y,x); 119 } 120 dfs(1); 121 for (int i=1;i<=n;i++) 122 { 123 int t=num[i];//從標號的1開始。 124 change(1,top,root[fx[fa[t][0]]],root[i],a[t]); 125 } 126 int last=0; 127 for(int i=1;i<=m;i++) 128 { 129 int x=read(),y=read(),rk=read(); 130 x^=last; 131 last=que(x,y,rk); 132 printf("%d",last); 133 if(i!=m)printf("\n"); 134 } 135 /*for (int i=1;i<=m;i++) 136 { 137 int x=read(),y=read(),rank=read(); 138 x^=last; 139 int a=root[fx[x]],b=root[fx[y]],c=root[fx[lca(x,y)]],d=root[fx[fa[lca(x,y)][0]]]; 140 last=query(1,top,a,b,c,d,rank); 141 printf("%d",last); 142 if (i!=m) cout<<endl; 143 }*/ 144 }

Wrong代碼

  1 #include<cstring>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstdio>
  6 
  7 #define N 100007
  8 #define M 3000007
  9 using namespace std;
 10 inline int read()
 11 {
 12     int x=0,f=1;char ch=getchar();
 13     while(ch>9||ch<0){if (ch==-) f=-1;ch=getchar();}
 14     while(ch<=9&&ch>=0){x=(x<<3)+(x<<1)+ch-0;ch=getchar();}
 15     return x*f;
 16 }
 17 
 18 int n,m,top,sz,ind;
 19 int a[N],zhi[N];
 20 int num[N],fx[N];
 21 int cnt,head[N],next[2*N],rea[2*N];
 22 int ls[M],rs[M],sum[M],root[N];
 23 int deep[N],fa[N][17];
 24 
 25 int find(int x)
 26 {
 27     int l=1,r=top;
 28     while(l<=r)
 29     {
 30         int mid=(l+r)>>1;
 31         if (zhi[mid]==x) return mid;
 32         if (zhi[mid]<x) l=mid+1;
 33         else r=mid-1;
 34     }
 35 }
 36 void add(int u,int v)
 37 {
 38     next[++cnt]=head[u];
 39     head[u]=cnt;
 40     rea[cnt]=v;
 41 }
 42 void dfs(int u)
 43 {
 44     ind++,num[ind]=u,fx[u]=ind;
 45     for (int i=1;i<=16;i++)
 46         fa[u][i]=fa[fa[u][i-1]][i-1];
 47     for (int i=head[u];i!=-1;i=next[i])
 48     {
 49         int v=rea[i];
 50         if (fa[u][0]!=v)
 51         {
 52             deep[v]=deep[u]+1;
 53             fa[v][0]=u;
 54             dfs(v);
 55         }
 56     }
 57 }
 58 int lca(int a,int b)
 59 {
 60     if (deep[a]<deep[b]) swap(a,b);
 61     int i;
 62     for (i=0;(1<<i)<=deep[a];i++);
 63     i--;
 64     for (int j=i;j>=0;j--)
 65         if (deep[a]-(1<<j)>=deep[b]) a=fa[a][j];
 66     if (a==b) return a;
 67     for (int j=i;j>=0;j--)
 68         if (fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j];
 69     return fa[a][0];        
 70 }
 71 void change(int l,int r,int x,int &y,int z)
 72 {
 73     y=++sz;
 74     sum[y]=sum[x]+1;
 75     if (l==r) return;
 76     ls[y]=ls[x],rs[y]=rs[x];
 77     int mid=(l+r)>>1;
 78     if (z<=mid) change(l,mid,ls[x],ls[y],z);
 79     else change(mid+1,r,rs[x],rs[y],z);
 80 }
 81 int query(int l,int r,int a,int b,int c,int d,int rank)
 82 {
 83     if (l==r) return zhi[l];
 84     int mid=(l+r)>>1,tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
 85     if (tmp>=rank) return query(l,mid,ls[a],ls[b],ls[c],ls[d],rank);
 86     else return query(mid+1,r,rs[a],rs[b],rs[c],rs[d],rank-tmp);
 87 }
 88 int main()
 89 {
 90     memset(head,-1,sizeof(head));
 91     n=read(),m=read();
 92     for (int i=1;i<=n;i++)
 93         a[i]=read(),zhi[i]=a[i];
 94     sort(zhi+1,zhi+n+1);
 95     top=1;
 96     for (int i=2;i<=n;i++)
 97         if (zhi[i]!=zhi[i-1]) zhi[++top]=zhi[i];
 98     for (int i=1;i<=n;i++)
 99         a[i]=find(a[i]);
100     for (int i=1;i<n;i++)
101     {
102         int x=read(),y=read();
103         add(x,y),add(y,x);
104     }
105     dfs(1);
106     for (int i=1;i<=n;i++)
107     {
108         int t=num[i];//從標號的1開始。 
109         change(1,top,root[fx[fa[t][0]]],root[i],a[t]);
110     }
111     int last=0;
112     for (int i=1;i<=m;i++)
113     {
114         int x=read(),y=read(),rank=read();
115         x^=last;
116         int a=root[fx[x]],b=root[fx[y]],c=root[fx[lca(x,y)]],d=root[fx[fa[lca(x,y)][0]]];
117         last=query(1,top,a,b,c,d,rank);
118         printf("%d",last);
119         if (i!=m) cout<<endl;
120     }
121 }

bzoj 2588 Spoj 10628. Count on a tree (可持久化線段樹)