zoukankan      html  css  js  c++  java
  • 【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]
  • 相关阅读:
    系统数据库如何恢复Master数据库
    在Orderby子句中使用CASE 语句
    SQL NOTECURSOR
    MVC 中静态文件部分动态化
    SQL NOTCTE
    Get data style from Excel
    SQL NOTPARTITION
    LAMDA表达式学习
    SQL NOTEVARIABLE
    起II6.0中使用windows2003自带的虚拟主机管理系统
  • 原文地址:https://www.cnblogs.com/Tunix/p/4341321.html
Copyright © 2011-2022 走看看