zoukankan      html  css  js  c++  java
  • GERALD07加强版题解

    题目描述:

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

    输入格式:

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

    输出格式:

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

    题解:

      连通问题首先考虑LCT。

      考虑连通块个数的计算方法。

      连通块个数=点数-去掉重边后的边数。

      逐个枚举边,如果这条边连接的两个点没有连通,连接这条边;反之,把两点间最早的边弹出,连接这条边,并记录弹出边的编号。

      每次查询区间时,如果这条边弹出的边在区间内,那么这条边是无效的。

      所以问题转化为求区间内小于某个数的数的个数,可以主席树维护。

      时间复杂度$O(nlog_n)$

    Code:

      1 #include<iostream>
      2 #include<cstdio>
      3 using namespace std;
      4 const int N=400010;
      5 const int inf=1e9+10;
      6 int n,m,k,ty,cnt,top;
      7 int a[N<<1],st[N<<1],ch[N<<1][2],f[N<<1],rev[N<<1],mi[N<<1];
      8 int u[N],v[N],rt[N],b[N],an[N];
      9 struct seg{
     10     int lc,rc,w;
     11 }t[N<<5];
     12 int read()
     13 {
     14     int s=0;char c=getchar();
     15     while(c<'0'||c>'9') c=getchar();
     16     while(c>='0'&&c<='9'){
     17         s=(s<<3)+(s<<1)+c-'0';
     18         c=getchar();
     19     }
     20     return s;
     21 }
     22 int get(int x)
     23 {
     24     return ch[f[x]][1]==x;
     25 }
     26 bool isroot(int x)
     27 {
     28     return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
     29 }
     30 void pushup(int x)
     31 {
     32     mi[x]=a[x];
     33     if(ch[x][0]) mi[x]=min(mi[x],mi[ch[x][0]]);
     34     if(ch[x][1]) mi[x]=min(mi[x],mi[ch[x][1]]);
     35 }
     36 void pushdown(int x)
     37 {
     38     if(rev[x]){
     39         swap(ch[x][0],ch[x][1]);
     40         if(ch[x][0]) rev[ch[x][0]]^=1;
     41         if(ch[x][1]) rev[ch[x][1]]^=1;
     42         rev[x]=0;
     43     }
     44 }
     45 void rotate(int x)
     46 {
     47     int y=f[x],z=f[y],k=get(x);
     48     if(!isroot(y)){
     49         if(ch[z][0]==y) ch[z][0]=x;
     50         else ch[z][1]=x;
     51     }
     52     f[x]=z;f[y]=x;f[ch[x][k^1]]=y;
     53     ch[y][k]=ch[x][k^1];ch[x][k^1]=y;
     54     pushup(y);pushup(x);
     55 }
     56 void splay(int x)
     57 {
     58     top=0;st[++top]=x;
     59     for(int i=x;!isroot(i);i=f[i]) st[++top]=f[i];
     60     for(int i=top;i>=1;i--) pushdown(st[i]);
     61     while(!isroot(x)){
     62         int y=f[x];
     63         if(!isroot(y)){
     64             if(get(x)==get(y)) rotate(y);
     65             else rotate(x);
     66         }
     67         rotate(x);
     68     }
     69 }
     70 void access(int x)
     71 {
     72     for(int y=0;x;y=x,x=f[x]){
     73         splay(x);ch[x][1]=y;pushup(x);
     74     }
     75 }
     76 void makeroot(int x)
     77 {
     78     access(x);splay(x);
     79     rev[x]^=1;
     80 }
     81 void split(int x,int y)
     82 {
     83     makeroot(x);
     84     access(y);splay(y);
     85 }
     86 void link(int x,int y)
     87 {
     88     makeroot(x);
     89     f[x]=y;
     90 }
     91 void cut(int x,int y)
     92 {
     93     split(x,y);
     94     f[x]=ch[y][0]=0;
     95 }
     96 int find(int x)
     97 {
     98     access(x);splay(x);
     99     pushdown(x);
    100     while(ch[x][0]){
    101         pushdown(ch[x][0]);
    102         x=ch[x][0];
    103     }
    104     splay(x);
    105     return x;
    106 }
    107 void insert(int lk,int &rk,int l,int r,int x)
    108 {
    109     if(rk==0) rk=++cnt;
    110     t[rk].w=t[lk].w+1;
    111     if(l==r) return;
    112     int mid=(l+r)>>1;
    113     if(x<=mid){
    114         t[rk].rc=t[lk].rc;
    115         insert(t[lk].lc,t[rk].lc,l,mid,x);
    116     }
    117     else{
    118         t[rk].lc=t[lk].lc;
    119         insert(t[lk].rc,t[rk].rc,mid+1,r,x);
    120     }
    121 }
    122 int que(int lk,int rk,int L,int R,int l,int r)
    123 {
    124     if(L>=l&&R<=r) return t[rk].w-t[lk].w;
    125     int mid=(L+R)>>1;
    126     if(r<=mid) return que(t[lk].lc,t[rk].lc,L,mid,l,r);
    127     else if(l>mid) return que(t[lk].rc,t[rk].rc,mid+1,R,l,r);
    128     else return que(t[lk].lc,t[rk].lc,L,mid,l,r)+que(t[lk].rc,t[rk].rc,mid+1,R,l,r);
    129 }
    130 int main()
    131 {
    132     n=read();m=read();k=read();ty=read();
    133     for(int i=1;i<=n;i++) a[i]=inf;
    134     for(int i=1;i<=m;i++){
    135         u[i]=read();v[i]=read();a[i+n]=i;
    136         if(u[i]!=v[i]){
    137             int x=find(u[i]),y=find(v[i]);
    138             if(x==y){
    139                 split(u[i],v[i]);
    140                 b[i]=mi[v[i]];
    141                 cut(u[b[i]],b[i]+n);
    142                 cut(b[i]+n,v[b[i]]);
    143             }
    144             link(u[i],i+n);
    145             link(i+n,v[i]);
    146             insert(rt[i-1],rt[i],0,m,b[i]);
    147         }
    148         else rt[i]=rt[i-1];
    149     }
    150     for(int i=1;i<=k;i++){
    151         int l=read(),r=read();
    152         if(ty){
    153             l^=an[i-1];r^=an[i-1];
    154         }
    155         an[i]=n-que(rt[l-1],rt[r],0,m,0,l-1);
    156     }
    157     for(int i=1;i<=k;i++) printf("%d
    ",an[i]);
    158     return 0;
    159 }
    View Code
  • 相关阅读:
    css(上)
    前端基础
    并发编程,python的进程,与线程
    网络编程 套接字socket TCP UDP
    python 类的内置函数2
    python3大特征之多态
    python 类(object)的内置函数
    类 与 继承
    类 与 面向对象
    OOP >>> 封装
  • 原文地址:https://www.cnblogs.com/hz-Rockstar/p/11573740.html
Copyright © 2011-2022 走看看