码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ】【2588】COT(Count On a Tree)

时间:2015-03-16 12:45:35      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:

可持久化线段树


  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

 

【BZOJ】【2588】COT(Count On a Tree)

标签:

原文地址:http://www.cnblogs.com/Tunix/p/4341321.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!