zoukankan      html  css  js  c++  java
  • BZOJ3514:GERALD07加强版(LCT,主席树)

    Description

    N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

    Input

    第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。
    接下来M行,代表图中的每条边。
    接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。

    Output

     K行每行一个整数代表该组询问的联通块个数。

    Sample Input

    3 5 4 0
    1 3
    1 2
    2 1
    3 2
    2 2
    2 3
    1 5
    5 5
    1 2

    Sample Output

    2
    1
    3
    1

    HINT

    对于100%的数据,1≤N、M、K≤200,000。

    Solution

    $namespace$真是个好东西QAQ

    每次往里加边,如果构成环的话就把最早的那条边删掉,这个可以用$LCT$随便做。

    定义一个数组$Early[i]$,表示加第$i$条边的时候,会把哪条边删掉。

    特殊的,如果不删边,$Early[i]=0$。如果第$i$条边是自环,$Early[i]=i$。

    然后对$Early$数组建主席树,每次询问的答案就是$[l,r]$区间内小于等于$l-1$的数个个数。

    正确性……如果一条边$i$的$Early[i]$在$l$后面的话,那么加入$i$的时候,因为会产生环所以不会对连通块情况产生影响。否则如果$Early[i]$在$l$的前面的话,加入$i$就会对连通块情况产生影响……

    大体就是这样子具体我也不会

    Code

      1 #include<iostream>
      2 #include<cstdio>
      3 #define N (400009)
      4 using namespace std;
      5 
      6 int n,m,k,opt,Early[N],x[N],y[N];
      7 
      8 namespace LCT
      9 {
     10     int Father[N],Son[N][2],Val[N],Min[N],Rev[N];
     11 
     12     int Get(int x)
     13     {
     14         return Son[Father[x]][1]==x;
     15     }
     16     int Is_root(int x)
     17     {
     18         return Son[Father[x]][0]!=x && Son[Father[x]][1]!=x;
     19     }
     20     void Pushup(int x)
     21     {
     22         Min[x]=x;
     23         int ls=Son[x][0],rs=Son[x][1];
     24         if (Val[Min[ls]]<Val[Min[x]]) Min[x]=Min[ls];
     25         if (Val[Min[rs]]<Val[Min[x]]) Min[x]=Min[rs];
     26     }
     27     void Pushdown(int x)
     28     {
     29         if (Rev[x])
     30         {
     31             Rev[Son[x][0]]^=1;
     32             Rev[Son[x][1]]^=1;
     33             swap(Son[x][0],Son[x][1]);
     34             Rev[x]=0;
     35         }
     36     }
     37     void Rotate(int x)
     38     {
     39         int wh=Get(x);
     40         int fa=Father[x],fafa=Father[fa];
     41         if (!Is_root(fa)) Son[fafa][Son[fafa][1]==fa]=x;
     42         Father[fa]=x; Son[fa][wh]=Son[x][wh^1];
     43         if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
     44         Father[x]=fafa; Son[x][wh^1]=fa;
     45         Pushup(fa); Pushup(x);
     46     }
     47     void Push(int x)
     48     {
     49         if (!Is_root(x)) Push(Father[x]);
     50         Pushdown(x);
     51     }
     52     void Splay(int x)
     53     {
     54         Push(x);
     55         for (int fa; !Is_root(x); Rotate(x))
     56             if (!Is_root(fa=Father[x]))
     57                 Rotate(Get(fa)==Get(x)?fa:x);
     58     }
     59     void Access(int x)
     60     {
     61         for (int y=0; x; y=x,x=Father[x])
     62             Splay(x), Son[x][1]=y, Pushup(x);
     63     }
     64     void Make_root(int x)
     65     {
     66         Access(x); Splay(x); Rev[x]^=1;
     67     }
     68     int Find_root(int x)
     69     {
     70         Access(x); Splay(x);
     71         while (Son[x][0]) x=Son[x][0];
     72         return x;
     73     }
     74     void Link(int x,int y)
     75     {
     76         Make_root(x); Father[x]=y;
     77     }
     78     void Cut(int x,int y)
     79     {
     80         Make_root(x); Access(y); Splay(y);
     81         Son[y][0]=Father[x]=0; Pushup(y);
     82     }
     83     int Query(int x,int y)
     84     {
     85         Make_root(x); Access(y); Splay(y);
     86         return Min[y];
     87     }
     88     void Build_Early()
     89     {
     90         for (int i=1; i<=m; ++i) Val[n+i]=i;
     91         for (int i=0; i<=n; ++i) Val[i]=2e8,Min[i]=i;
     92         for (int i=1; i<=m; ++i)
     93         {
     94             scanf("%d%d",&x[i],&y[i]);
     95             if (x[i]==y[i]) {Early[i]=i; continue;}
     96             if (Find_root(x[i])!=Find_root(y[i]))
     97                 Link(x[i],i+n), Link(y[i],i+n);
     98             else
     99             {
    100                 int p=Query(x[i],y[i]);
    101                 Early[i]=p-n;
    102                 Cut(x[p-n],p); Cut(y[p-n],p);
    103                 Link(x[i],i+n); Link(y[i],i+n);
    104             }
    105         }
    106     }
    107 }
    108 
    109 namespace Sgt
    110 {
    111     struct Sgt{int ls,rs,val;}Segt[N*40];
    112     int sgt_num,Root[N];
    113 
    114     int Update(int pre,int l,int r,int x)
    115     {
    116         int now=++sgt_num;
    117         Segt[now]=Segt[pre];
    118         Segt[now].val++;
    119         if (l==r) return now;
    120         int mid=(l+r)>>1;
    121         if (x<=mid) Segt[now].ls=Update(Segt[now].ls,l,mid,x);
    122         else Segt[now].rs=Update(Segt[now].rs,mid+1,r,x);
    123         return now;
    124     }
    125     int Query(int u,int v,int l,int r,int l1,int r1)
    126     {
    127         if (l>r1 || r<l1) return 0;
    128         if (l1<=l && r<=r1) return Segt[v].val-Segt[u].val;
    129         int mid=(l+r)>>1;
    130         return Query(Segt[u].ls,Segt[v].ls,l,mid,l1,r1)+Query(Segt[u].rs,Segt[v].rs,mid+1,r,l1,r1);
    131     }
    132     void Solve()
    133     {
    134         for (int i=1; i<=m; ++i)
    135             Root[i]=Update(Root[i-1],0,2e5,Early[i]);
    136         int ans=0,l,r;
    137         for (int i=1; i<=k; ++i)
    138         {
    139             scanf("%d%d",&l,&r);
    140             if (opt) l^=ans, r^=ans;
    141             ans=n-Query(Root[l-1],Root[r],0,2e5,0,l-1);
    142             printf("%d
    ",ans);
    143         }
    144     }
    145 }
    146 
    147 int main()
    148 {
    149     scanf("%d%d%d%d",&n,&m,&k,&opt);
    150     LCT::Build_Early();
    151     Sgt::Solve();
    152 }
  • 相关阅读:
    Java反射实现几种方式
    kettle之几个.bat初步介绍
    eclipse 启动项目时候报的错误
    转:kettle中调度kitchen.bat后面接参数,写定时更新任务
    hibernate4,manytomany
    hibernate4,onetomany
    Javascript系列之在HTML中使用JavaScript
    Javascript系列之js简介
    004 C++ 指针
    003 C++ 函数
  • 原文地址:https://www.cnblogs.com/refun/p/10088908.html
Copyright © 2011-2022 走看看