• 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 }
  • 相关阅读:
    WinForm窗体间传值
    C# 把字符串类型日期转换为日期类型
    datagridview数据导出到excel
    C#中对文件的操作小结
    保证应用程序只有一个实例运行
    c#读取excel到dataset
    让select下的option选中
    使用mpvue开发小程序教程(二)
    手把手教你用vue-cli构建一个简单的路由应用
    wangEditor
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8341542.html
Copyright © 2020-2023  润新知