• BZOJ


    题目链接

    先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树。当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组。树的结点数可以用并查集来维护。总复杂度$O(nlog^2n)$。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10,inf=0x3f3f3f3f;
     5 int a[N],b[N],n2,hd[N],ne,n,m,nq,fa[N][20],dep[N],siz[N],fa2[N],rt[N],ls[N*100],rs[N*100],val[N*100],tot,vis[N];
     6 struct E {int v,nxt;} e[N<<1];
     7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     8 int fd(int x) {return ~fa2[x]?fa2[x]=fd(fa2[x]):x;}
     9 int mgg(int x,int y) {
    10     int fx=fd(x),fy=fd(y);
    11     if(fx==fy)return 0;
    12     fa2[fx]=fy,siz[fy]+=siz[fx];
    13     return 1;
    14 }
    15 #define mid ((l+r)>>1)
    16 int lca(int u,int v) {
    17     if(dep[u]<dep[v])swap(u,v);
    18     for(int i=19; i>=0&&dep[u]>dep[v]; --i)if(dep[fa[u][i]]>=dep[v])u=fa[u][i];
    19     if(u==v)return u;
    20     for(int i=19; i>=0; --i)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
    21     return fa[u][0];
    22 }
    23 void upd(int& u,int v,int x,int l=1,int r=n2) {
    24     if(!u)u=++tot;
    25     val[u]=val[v]+1;
    26     if(l==r)return;
    27     if(x<=mid)upd(ls[u],ls[v],x,l,mid),rs[u]=rs[v];
    28     else upd(rs[u],rs[v],x,mid+1,r),ls[u]=ls[v];
    29 }
    30 int qry(int u,int v,int w1,int w2,int k,int l=1,int r=n2) {
    31     if(l==r)return l;
    32     int cnt=val[ls[u]]+val[ls[v]]-val[ls[w1]]-val[ls[w2]];
    33     return k<=cnt?qry(ls[u],ls[v],ls[w1],ls[w2],k,l,mid):qry(rs[u],rs[v],rs[w1],rs[w2],k-cnt,mid+1,r);
    34 }
    35 void dfs(int u,int f,int d,int flag) {
    36     if(flag&&vis[u])return;
    37     vis[u]=1;
    38     fa[u][0]=f,dep[u]=d,rt[u]=0,upd(rt[u],rt[f],a[u]);
    39     for(int i=1; i<20; ++i)fa[u][i]=fa[fa[u][i-1]][i-1];
    40     for(int i=hd[u]; ~i; i=e[i].nxt) {
    41         int v=e[i].v;
    42         if(v==f)continue;
    43         dfs(v,u,d+1,flag);
    44     }
    45 }
    46 void mg(int u,int v) {
    47     if(siz[fd(u)]>siz[fd(v)])swap(u,v);
    48     addedge(u,v),addedge(v,u),mgg(u,v),dfs(u,v,dep[v]+1,0);
    49 }
    50 int main() {
    51     scanf("%*d");
    52     memset(hd,-1,sizeof hd),ne=0;
    53     memset(fa2,-1,sizeof fa2);
    54     scanf("%d%d%d",&n,&m,&nq);
    55     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    56     for(int i=1; i<=n; ++i)b[i-1]=a[i];
    57     sort(b,b+n),n2=unique(b,b+n)-b;
    58     for(int i=1; i<=n; ++i)a[i]=lower_bound(b,b+n2,a[i])-b+1;
    59     for(int i=1; i<=n; ++i)siz[i]=1;
    60     while(m--) {
    61         int u,v;
    62         scanf("%d%d",&u,&v);
    63         addedge(u,v),addedge(v,u),mgg(u,v);
    64     }
    65     for(int i=1; i<=n; ++i)dfs(i,0,1,1);
    66     for(int last=0; nq--;) {
    67         char ch;
    68         int u,v,k;
    69         scanf(" %c",&ch);
    70         if(ch=='Q') {
    71             scanf("%d%d%d",&u,&v,&k),u^=last,v^=last,k^=last;
    72             int w=lca(u,v),ans=b[qry(rt[u],rt[v],rt[w],rt[fa[w][0]],k)-1];
    73             printf("%d
    ",ans),last=ans;
    74         } else {
    75             scanf("%d%d",&u,&v),u^=last,v^=last;
    76             mg(u,v);
    77         }
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    cd的使用
    转换器模式
    装饰模式
    策略模式
    模板方法模式
    工厂模式
    类型信息
    proto编译组件使用
    proto编译引用外部包问题
    Kafka经典三大问:数据有序丢失重复
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10606939.html
Copyright © 2020-2023  润新知