BZOJ - 3123 森林 (可持久化线段树+启发式合并)

题目链接

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

 

posted @ 2019-03-27 13:37  jrltx  阅读(213)  评论(0编辑  收藏  举报