BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]

ZHX的题目。

类似于HH的项链我们考虑最后加入哪一条边以后合并了两个联通块,所以我们边权从大到小排然后依次加入。找出最晚加入的,记成last。

然后做主席树就好啦!

注意拆边为点。

By:大奕哥

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1e6+5;
  4 int c[N][2],mx[N],fa[N],w[N],pos[N],rev[N],s[N];
  5 int last[N],rt[N],cnt,n,m,k,type,ans,l,r;
  6 struct node{
  7     int s,l,r;
  8 }t[N<<2];
  9 struct edge{
 10     int x,y;
 11 }a[N];
 12 bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
 13 void update(int x)
 14 {
 15     mx[x]=w[x];pos[x]=x;
 16     if(mx[x]<mx[c[x][0]])mx[x]=mx[c[x][0]],pos[x]=pos[c[x][0]];
 17     if(mx[x]<mx[c[x][1]])mx[x]=mx[c[x][1]],pos[x]=pos[c[x][1]];
 18     return;
 19 }
 20 void pushup(int x)
 21 {
 22     if(rev[x])
 23     {
 24         rev[x]^=1;rev[c[x][0]]^=1;rev[c[x][1]]^=1;
 25         swap(c[x][0],c[x][1]);
 26     }
 27     return;
 28 }
 29 void rotate(int x)
 30 {
 31     int y=fa[x],z=fa[y],l,r;
 32     l=c[y][1]==x;r=l^1;
 33     if(!isroot(y))c[z][c[z][1]==y]=x;
 34     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
 35     c[y][l]=c[x][r];c[x][r]=y;
 36     update(y);update(x);
 37     return;
 38 }
 39 void splay(int x)
 40 {
 41     int top=0,i;
 42     for(i=x;!isroot(i);i=fa[i])s[++top]=i;s[++top]=i;
 43     for(i=top;i;--i)pushup(s[i]);
 44     while(!isroot(x))
 45     {
 46 //        cout<<x<<endl;
 47         int y=fa[x],z=fa[y];
 48         if(!isroot(y))
 49         {
 50             if(c[y][0]==x^c[z][0]==y)rotate(x);
 51             else rotate(y);
 52         }
 53         rotate(x);
 54     }
 55     return;
 56 }
 57 void access(int x)
 58 {
 59     int y=0;
 60     while(x)
 61     {
 62         splay(x);
 63         c[x][1]=y;
 64         y=x;x=fa[x];
 65     }
 66     return;
 67 }
 68 void mroot(int x)
 69 {
 70     access(x);splay(x);rev[x]^=1;
 71 }
 72 void cut(int x,int y)
 73 {
 74     mroot(x);access(y);splay(y);c[y][0]=fa[x]=0;
 75 }
 76 void link(int x,int y)
 77 {
 78     mroot(x);fa[x]=y;splay(x);
 79 }
 80 int query(int x,int y)
 81 {
 82     mroot(x);access(y);splay(y);return pos[c[y][0]];
 83 }
 84 int f[N];
 85 inline int get(int x)
 86 {
 87     return x==f[x]?x:f[x]=get(f[x]);
 88 }
 89 void solve()
 90 {
 91     for(int i=1;i<=n+m;++i)f[i]=i;
 92     for(int i=1;i<=m;++i)
 93     {
 94         int fx=get(a[i].x);int fy=get(a[i].y);
 95         if(a[i].x==a[i].y){
 96             last[i]=i;continue;
 97         }
 98         if(fx==fy)
 99         {
100             int tmp=query(a[i].x,a[i].y);
101             last[i]=tmp-n;
102             cut(tmp,a[tmp-n].x);cut(tmp,a[tmp-n].y);
103         }
104         link(a[i].x,i+n);link(a[i].y,i+n);f[fx]=fy;
105     }
106     return;
107 }
108 void change(int &x,int l,int r,int pos)
109 {
110     t[++cnt]=t[x];x=cnt;
111     if(l==r){
112         t[x].s++;return;
113     }
114     int mid=l+r>>1;
115     if(pos>mid)change(t[x].r,mid+1,r,pos);
116     else change(t[x].l,l,mid,pos);
117     t[x].s=t[t[x].l].s+t[t[x].r].s;
118     return;
119 }
120 int querysum(int x,int y,int l,int r,int L,int R)
121 {
122     if(l==L&&r==R)return t[y].s-t[x].s;
123     int mid=l+r>>1;
124     if(mid>=R)return querysum(t[x].l,t[y].l,l,mid,L,R);
125     else if(mid<L)return querysum(t[x].r,t[y].r,mid+1,r,L,R);
126     else return querysum(t[x].l,t[y].l,l,mid,L,mid)+querysum(t[x].r,t[y].r,mid+1,r,mid+1,R);
127 }
128 void work()
129 {
130     for(int i=1;i<=m;++i)rt[i]=rt[i-1],change(rt[i],0,m,last[i]);
131     for(int i=1;i<=k;++i)
132     {
133         scanf("%d%d",&l,&r);if(type)l^=ans,r^=ans;
134         ans=querysum(rt[l-1],rt[r],0,m,0,l-1);ans=n-ans;
135         printf("%d
",ans);
136     }
137 }
138 int main()
139 {
140     scanf("%d%d%d%d",&n,&m,&k,&type);
141     for(int i=1;i<=m;++i)
142     {
143         scanf("%d%d",&a[i].x,&a[i].y);
144         w[i+n]=m+n-i+1;mx[i+n]=m+n-i+1;pos[i+n]=i+n;
145     }
146     solve();
147     work();
148     return 0;
149 }
原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8341542.html