zoukankan      html  css  js  c++  java
  • 【SDOI2013】森林

    链接

    先考虑对于一棵树进行路径查询,当然可以树链剖分,但没必要。

    对于一个询问 [ x , y ] ,可以转化为 [ x , root ] + [ y , root ] - 2 [ lca , root ] + lca,即 [ x , root ] + [ y , root ] - [ lca , root ] - [ fa [ lca ] , root ]

    所以只要统计节点到根节点的信息就可以了,求第k小,显然要用主席树。

    我们知道,主席树的基本思想是前缀和,在序列上时,以前一个为pre;在树上时,只要以这个节点的父亲为pre就可以了。

    这样就解决了询问。

    对于连边,可以启发式合并。简而言之就是小树往大树上连。

    启发式合并中,每个节点只有在当前size较小时才会被合并,每次合并后体积至少扩大为原来的两倍。所以总复杂度是O(NlogN)。因为更新倍增数组和插入是O(logN)的,所以带了两个log,还是可以接受的。

    最后注意要离散化,数组要开大。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<string>
      4 #include<cstring>
      5 #include<cstdlib>
      6 using namespace std;
      7 
      8 int read(){
      9     int x=0;char ch=getchar();
     10     while(ch<'0'||ch>'9')ch=getchar();
     11     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
     12     return x;
     13 }
     14 
     15 const int N=80005;
     16 
     17 int testcase,n,m,t,ans=0;
     18 char op[3];
     19 int x,y,k;
     20 
     21 struct node{
     22     int y,nxt;
     23 }e[N*4];
     24 int h[N],tot=0;
     25 void ad(int x,int y){
     26     ++tot;e[tot].y=y;e[tot].nxt=h[x];h[x]=tot;
     27 }
     28 
     29 int fa[N];
     30 int find(int x){
     31     return x==fa[x]?x:fa[x]=find(fa[x]);
     32 }
     33 
     34 int root[N],cnt=0;;
     35 int val[N],b[N],len;
     36 struct Tree{
     37     int ls,rs,sz;
     38 }tr[N*600];
     39 int build(int l,int r){
     40     int rt=++cnt;
     41     tr[rt].sz=0;
     42     if(l==r)return rt;
     43     int mid=(l+r)>>1;
     44     tr[rt].ls=build(l,mid);
     45     tr[rt].rs=build(mid+1,r);
     46     return rt;
     47 }
     48 int sz[N],st[N][18],dep[N],vis[N];
     49 int Hash(int x){
     50     return lower_bound(b+1,b+len+1,x)-b;
     51 }
     52 void insert(int &now,int pre,int l,int r,int x){
     53     now=++cnt;
     54     tr[now]=tr[pre];++tr[now].sz;
     55     if(l==r)return;
     56     int mid=(l+r)>>1;
     57     if(x<=mid)insert(tr[now].ls,tr[pre].ls,l,mid,x);
     58     else insert(tr[now].rs,tr[pre].rs,mid+1,r,x);
     59 }
     60 void dfs(int x,int father,int rt){
     61     dep[x]=dep[father]+1;
     62     st[x][0]=father;++sz[rt];
     63     vis[x]=1;fa[x]=father;
     64     for(int j=1;j<=17;++j)st[x][j]=st[st[x][j-1]][j-1];
     65     insert(root[x],root[father],1,len,Hash(val[x]));
     66     for(int i=h[x];i;i=e[i].nxt){
     67         int y=e[i].y;
     68         if(y==father)continue;
     69         dfs(y,x,rt);
     70     }
     71 }
     72 int LCA(int x,int y){
     73     if(dep[x]<dep[y])swap(x,y);
     74     for(int j=17;j>=0;--j)if(dep[st[x][j]]>=dep[y])x=st[x][j];
     75     if(x==y)return x;
     76     for(int j=17;j>=0;--j){
     77         if(st[x][j]!=st[y][j])x=st[x][j],y=st[y][j];
     78     }
     79     return st[x][0];
     80 }
     81 int ask(int x,int y,int lca,int flca,int l,int r,int k){
     82     if(l==r)return b[l];
     83     int lsz=tr[tr[x].ls].sz+tr[tr[y].ls].sz-tr[tr[lca].ls].sz-tr[tr[flca].ls].sz;
     84     int mid=(l+r)>>1;
     85     if(k<=lsz)return ask(tr[x].ls,tr[y].ls,tr[lca].ls,tr[flca].ls,l,mid,k);
     86     return ask(tr[x].rs,tr[y].rs,tr[lca].rs,tr[flca].rs,mid+1,r,k-lsz);
     87 }
     88 
     89 int main(){
     90     testcase=read();n=read();m=read();t=read();
     91     for(int i=1;i<=n;++i){
     92         val[i]=read();b[i]=val[i];fa[i]=i;
     93     }
     94     sort(b+1,b+n+1);
     95     len=unique(b+1,b+n+1)-b-1;
     96     while(m--){
     97         x=read();y=read();
     98         ad(x,y);ad(y,x);
     99     }
    100     root[0]=build(1,len);
    101     for(int i=1;i<=n;++i){
    102         if(!vis[i])dfs(i,0,i),fa[i]=i;
    103     }
    104     while(t--){
    105         scanf("%s",op);
    106         x=read();y=read();
    107         x^=ans,y^=ans;
    108         if(op[0]=='L'){
    109             ad(x,y);ad(y,x);
    110             int fx=find(x),fy=find(y);
    111             if(sz[fx]>sz[fy]){
    112                 swap(x,y);swap(fx,fy);
    113             }
    114             dfs(x,y,fy);
    115         }
    116         else {
    117             k=read();k^=ans;
    118             int lca=LCA(x,y);
    119             ans=ask(root[x],root[y],root[lca],root[st[lca][0]],1,len,k);
    120             printf("%d
    ",ans);
    121         }
    122     }
    123 }
  • 相关阅读:
    剑指office--------重建二叉树
    剑指office--------二进制中1的个数
    剑指office--------最小的K个数 (待补充)
    剑指office--------二维数组的查找
    剑指office--------替换空格
    Redis集群
    一致性hash算法
    Zab协议(转)
    Redis线程模型
    Http Cookie和session
  • 原文地址:https://www.cnblogs.com/chiyo/p/11391362.html
Copyright © 2011-2022 走看看