【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 }
View Code

倍增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 }
View Code

 

2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

2
8
9
105
7

HINT




HINT:

N,M<=100000

暴力自重。。。

Source

[Submit][Status][Discuss]
posted @ 2015-03-16 11:05  Tunix  阅读(187)  评论(0编辑  收藏  举报