【BZOJ】【2588】COT(Count On a Tree)
可持久化线段树
maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树。
然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 1901
然后rausen(Orz!!!)粗来跟我说:你直接减去lca和fa[lca]不就好啦~搞树剖还多一个log……
我恍然大悟!然后两个都交了一下,事实证明:我链剖写的还行,LCA写的太丑……速度反而是多一个log的链剖快QAQ(另:因为边少我就偷懒没写边表,直接vector水过)
链剖:
1 /************************************************************** 2 Problem: 2588 3 User: ProgrammingApe 4 Language: C++ 5 Result: Accepted 6 Time:3768 ms 7 Memory:47652 kb 8 ****************************************************************/ 9 10 //BZOJ 2588 11 #include<vector> 12 #include<cstdio> 13 #include<cstring> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 inline int getint(){ 22 int v=0,sign=1; char ch=getchar(); 23 while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();} 24 while(isdigit(ch)) {v=v*10+ch-'0'; ch=getchar();} 25 return v*sign; 26 } 27 const int N=1e5+10,INF=~0u>>2; 28 /*******************template********************/ 29 struct tree{ 30 int cnt,l,r; 31 }t[N*30]; 32 int root[N],cnt,num; 33 int lc,rc,ln[N],rn[N]; 34 #define mid (l+r>>1) 35 void update(int &o,int l,int r,int pos){ 36 t[++cnt]=t[o]; o=cnt; t[o].cnt++; 37 if (l==r) return; 38 if (pos<=mid) update(t[o].l,l,mid,pos); 39 else update(t[o].r,mid+1,r,pos); 40 } 41 int query_t(int rank){ 42 int l=1,r=num; 43 int tl=0,tr=0; 44 while(l!=r){ 45 tl=tr=0; 46 F(i,1,lc) tl+=t[t[ln[i]].l].cnt; 47 F(i,1,rc) tr+=t[t[rn[i]].l].cnt; 48 if (tr-tl>=rank){ 49 F(i,1,lc) ln[i]=t[ln[i]].l; 50 F(i,1,rc) rn[i]=t[rn[i]].l; 51 r=mid; 52 }else{ 53 F(i,1,lc) ln[i]=t[ln[i]].r; 54 F(i,1,rc) rn[i]=t[rn[i]].r; 55 l=mid+1; rank-=tr-tl; 56 } 57 } 58 return l; 59 } 60 /*****************可持久化线段树 ***************/ 61 vector<int>G[N]; 62 int top[N],fa[N],son[N],dep[N],tot,size[N],a[N],b[N],n,m,lastans; 63 bool vis[N]; 64 void dfs(int x,int f,int d){ 65 vis[x]=1; 66 fa[x]=f; dep[x]=d; size[x]=1; son[x]=0; 67 int maxsize=0; 68 rep(i,G[x].size()){ 69 int to=G[x][i]; 70 if (vis[to]) continue; 71 dfs(to,x,d+1); 72 size[x]+=size[to]; 73 if (size[to]>maxsize) maxsize=size[to],son[x]=to; 74 } 75 } 76 void connect(int x,int f){ 77 vis[x]=1; 78 root[x]=root[fa[x]]; 79 update(root[x],1,num,a[x]); 80 // root[x]=++tot; 81 top[x]=f; 82 if (son[x]) connect(son[x],f); 83 rep(i,G[x].size()){ 84 int to=G[x][i]; 85 if (!vis[to]) connect(to,to); 86 } 87 } 88 void query(int x,int y,int k){ 89 lc=rc=0; 90 while(top[x]!=top[y]){ 91 if (dep[top[x]]<dep[top[y]]) swap(x,y); 92 ln[++lc]=root[fa[top[x]]]; rn[++rc]=root[x]; 93 x=fa[top[x]]; 94 } 95 if (dep[x]>dep[y]) swap(x,y); 96 ln[++lc]=root[fa[x]]; rn[++rc]=root[y]; 97 printf("%d",lastans=b[query_t(k)]); 98 } 99 /**********************链剖*********************/ 100 int main(){ 101 // freopen("input.txt","r",stdin); 102 n=getint(); m=getint(); 103 F(i,1,n) b[i]=a[i]=getint(); 104 sort(b+1,b+n+1); 105 num=unique(b+1,b+n+1)-b-1; 106 F(i,1,n) a[i]=lower_bound(b+1,b+num+1,a[i])-b; 107 108 int x,y,k; 109 F(i,2,n){ 110 x=getint(); y=getint(); 111 G[x].pb(y); G[y].pb(x); 112 } 113 dfs(1,0,1); 114 memset(vis,0,sizeof vis); 115 connect(1,1); 116 117 F(i,1,m){ 118 x=lastans^getint(); y=getint(); k=getint(); 119 query(x,y,k); 120 if (i!=m) puts(""); 121 } 122 return 0; 123 }
倍增LCA:
1 /************************************************************** 2 Problem: 2588 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:4520 ms 7 Memory:53024 kb 8 ****************************************************************/ 9 10 //BZOJ 2588 11 #include<vector> 12 #include<cstdio> 13 #include<cstring> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 inline int getint(){ 22 int v=0,sign=1; char ch=getchar(); 23 while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();} 24 while(isdigit(ch)) {v=v*10+ch-'0'; ch=getchar();} 25 return v*sign; 26 } 27 const int N=1e5+10,INF=~0u>>2; 28 /*******************template********************/ 29 struct tree{ 30 int cnt,l,r; 31 }t[N*30]; 32 int root[N],cnt,num; 33 int lc,rc,ln[N],rn[N]; 34 #define mid (l+r>>1) 35 void update(int &o,int l,int r,int pos){ 36 t[++cnt]=t[o]; o=cnt; t[o].cnt++; 37 if (l==r) return; 38 if (pos<=mid) update(t[o].l,l,mid,pos); 39 else update(t[o].r,mid+1,r,pos); 40 } 41 int query_t(int rank){ 42 int l=1,r=num; 43 int tl=0,tr=0; 44 while(l!=r){ 45 tl=tr=0; 46 F(i,1,lc) tl+=t[t[ln[i]].l].cnt; 47 F(i,1,rc) tr+=t[t[rn[i]].l].cnt; 48 if (tr-tl>=rank){ 49 F(i,1,lc) ln[i]=t[ln[i]].l; 50 F(i,1,rc) rn[i]=t[rn[i]].l; 51 r=mid; 52 }else{ 53 F(i,1,lc) ln[i]=t[ln[i]].r; 54 F(i,1,rc) rn[i]=t[rn[i]].r; 55 l=mid+1; rank-=tr-tl; 56 } 57 } 58 return l; 59 } 60 /*****************可持久化线段树 ***************/ 61 vector<int>G[N]; 62 int fa[N][18],dep[N],a[N],b[N],n,m,lastans; 63 void dfs(int x){ 64 F(i,1,17) 65 if (dep[x]>=(1<<i)) fa[x][i]=fa[fa[x][i-1]][i-1]; 66 else break; 67 root[x]=root[fa[x][0]]; 68 update(root[x],1,num,a[x]); 69 rep(i,G[x].size()){ 70 int to=G[x][i]; 71 if (to==fa[x][0]) continue; 72 fa[to][0]=x; dep[to]=dep[x]+1; 73 dfs(to); 74 } 75 } 76 int LCA(int x,int y){ 77 if (dep[x]<dep[y]) swap(x,y); 78 int t=dep[x]-dep[y]; 79 for(int i=0;(1<<i)<=t;i++) 80 if(t&(1<<i)) x=fa[x][i]; 81 D(i,17,0) 82 if(fa[x][i]!=fa[y][i]) 83 x=fa[x][i],y=fa[y][i]; 84 if (x==y) return x; 85 return fa[x][0]; 86 } 87 void query(int x,int y,int k){ 88 lc=rc=0; 89 int lca=LCA(x,y); 90 ln[++lc]=root[lca]; ln[++lc]=root[fa[lca][0]]; 91 rn[++rc]=root[x]; rn[++rc]=root[y]; 92 printf("%d",lastans=b[query_t(k)]); 93 } 94 /**********************LCA*********************/ 95 int main(){ 96 n=getint(); m=getint(); 97 F(i,1,n) b[i]=a[i]=getint(); 98 sort(b+1,b+n+1); 99 num=unique(b+1,b+n+1)-b-1; 100 F(i,1,n) a[i]=lower_bound(b+1,b+num+1,a[i])-b; 101 102 int x,y,k; 103 F(i,2,n){ 104 x=getint(); y=getint(); 105 G[x].pb(y); G[y].pb(x); 106 } 107 dfs(1); 108 109 F(i,1,m){ 110 x=lastans^getint(); y=getint(); k=getint(); 111 query(x,y,k); 112 if (i!=m) puts(""); 113 } 114 return 0; 115 }
2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 2581 Solved: 586
[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
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
8
9
105
7
HINT
HINT:
N,M<=100000
暴力自重。。。