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 }
  • 相关阅读:
    [译文] 实体与值对象到底是不是一回事?
    实现 WebApi 自托管服务宿主于 WinForms 及其交互
    [译文] C# 8 已成旧闻, 向前, 抵达 C# 9!
    [译文] 为什么你在 C# 里总是应该使用 "var" 关键字
    通过设置iis在局域网中访问网页
    windows 10 安装使用kafka
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定义命名化和类型化的客户端
    Asp.net Core 2.0 OpenId Connect Handler缺失Claims?
  • 原文地址:https://www.cnblogs.com/chiyo/p/11391362.html
Copyright © 2011-2022 走看看