• 【bzoj3514】Codechef MARCH14 GERALD07加强版


    3514: Codechef MARCH14 GERALD07加强版

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 2395  Solved: 922
    [Submit][Status][Discuss]

    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。


    2016.2.26提高时限至60s

     

    Source

    [Submit][Status][Discuss]

    题意:无向图,维护边的编号在[l,r]的边形成的点连通块个数;

    题解:  一般有一下一些情况:

               ① 无向图,维护边的编号在[l,r]的点连通块个数
               ②无向图,维护点的编号在[l,r]的生成子图连通块个数;

               ③强制在线??

    题解:好神

             ①将边按照编号不断加入LCT,如果没有形成环就直接加入,如果形成了一个环就删去环上编号最小的边,这样LCT里面会保留尽量靠后的边,将询问按右端点排序,答案是n - LCT里面编号在[l,r]的数目;

                可以用树状数组维护边编号;

              ②将点看成一个序列,将边(u,v)看成一条线段并按右端点排序,按照一样的方法不断加入边,只是这次有环就删去左端点编号最小的值,答案同样是[r-l+1]-LCT里面左端点编号在[l,r]的数目;

                也可以用树状数组维护;

              ③离线太白痴了,树状数组换成主席树就可以了,LCT维护边的信息时将边看成一个点;

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<queue>
      6 #include<cmath>
      7 #include<vector>
      8 #include<stack>
      9 #include<map>
     10 #define Run(i,l,r) for(int i=l;i<=r;i++)
     11 #define Don(i,l,r) for(int i=l;i>=r;i--)
     12 #define ll long long
     13 #define inf 0x3f3f3f3f
     14 using namespace std;
     15 const int N=200010; 
     16 int n,m,q,sz,typ,rt[N],ls[N*40],rs[N*40],sum[N*40];
     17 int ch[N<<1][2],fa[N<<1],mn[N<<1],val[N<<1],rev[N<<1];
     18 struct edge{int u,v;}e[N];
     19 char gc(){
     20     static char*p1,*p2,s[1000000];
     21     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
     22     return(p1==p2)?EOF:*p1++; 
     23 }//
     24 int rd(){
     25     int x=0; char c=gc();
     26     while(c<'0'||c>'9')c=gc();
     27     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
     28     return x;
     29 }//
     30 bool is_rt(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}//
     31 void pushup(int x){mn[x]=min(val[x],min(mn[ch[x][0]],mn[ch[x][1]]));}//
     32 void pushdown(int x){
     33     if(rev[x]){
     34         swap(ch[x][0],ch[x][1]);
     35         rev[ch[x][0]]^=1;
     36         rev[ch[x][1]]^=1;
     37         rev[x]^=1;
     38     }
     39 }//
     40 void rotate(int x){
     41     int y=fa[x] , z=fa[y];
     42     if(!is_rt(y))ch[z][ch[z][1]==y]=x;
     43     int l=ch[y][1]==x,r=l^1;
     44     fa[y]=x;fa[x]=z;fa[ch[x][r]]=y;
     45     ch[y][l]=ch[x][r];ch[x][r]=y;
     46     pushup(y),pushup(x);
     47 }//
     48 void push(int x){
     49     if(!is_rt(x))push(fa[x]);
     50     pushdown(x);
     51 }//
     52 void splay(int x){
     53     push(x);
     54     for(int y,z;!is_rt(x);rotate(x)){
     55         y=fa[x],z=fa[y];
     56         if(!is_rt(y))rotate((ch[z][1]==y)^(ch[y][1]==x) ? x : y);
     57     }
     58 }//
     59 void access(int x){
     60     push(x);
     61     for(int y=0;x;y=x,x=fa[x]){
     62         splay(x);
     63 //      fa[ch[x][1]]=0;  
     64         ch[x][1]=y;
     65         pushup(x);
     66     }
     67 }//
     68 int find(int x){
     69     access(x);splay(x);
     70     while(ch[x][0])x=ch[x][0];
     71     return x;
     72 }//
     73 void make_rt(int x){
     74     access(x);splay(x);
     75     rev[x]^=1;
     76 }//
     77 void link(int x,int y){
     78     make_rt(x);
     79     fa[x]=y;
     80 }//
     81 void cut(int x,int y){
     82     make_rt(x);
     83     access(y);splay(y);
     84     ch[y][0]=fa[x]=0;
     85     pushup(y);
     86 }//
     87 int ask(int x,int y){
     88     make_rt(x);
     89     access(y);splay(y);
     90     return mn[y];
     91 }//
     92 void ins(int&k,int last,int l,int r,int x,int v){
     93     sum[k=++sz]=sum[last]+v;
     94     ls[k]=ls[last];rs[k]=rs[last];
     95     int mid=(l+r)>>1;
     96     if(l==r)return ;
     97     if(x<=mid)ins(ls[k],ls[last],l,mid,x,v);
     98     else ins(rs[k],rs[last],mid+1,r,x,v);
     99 }//
    100 int query(int k,int l,int r,int x,int y){
    101     if(l==x&&r==y)return sum[k];
    102     else{
    103         int mid=(l+r)>>1;
    104         if(y<=mid)return query(ls[k],l,mid,x,y);
    105         else if(x>mid)return query(rs[k],mid+1,r,x,y);
    106         else return query(ls[k],l,mid,x,mid) + query(rs[k],mid+1,r,mid+1,y);
    107     }
    108 }//
    109 int main(){
    110 //  freopen("bzoj3514.in","r",stdin);
    111 //  freopen("bzoj3514.out","w",stdout);
    112     n=rd();m=rd();q=rd();typ=rd();
    113     mn[0]=val[0]=inf;
    114     for(int i=1;i<=n;i++)val[i]=inf;
    115     for(int i=1;i<=m;i++)e[i]=(edge){rd(),rd()},val[i+n]=i;
    116     for(int i=1;i<=m;i++){
    117         int u=e[i].u , v=e[i].v;
    118         if(u==v){rt[i]=rt[i-1];continue;}
    119         int fu = find(u) , fv = find(v);
    120         if(fu==fv){
    121             int x = ask(u,v);
    122             ins(rt[i],rt[i-1],1,m,x,-1);
    123             cut(e[x].u,x+n),cut(e[x].v,x+n);
    124         }else rt[i]=rt[i-1];
    125         ins(rt[i],rt[i],1,m,i,1);
    126         link(u,i+n),link(v,i+n);
    127     }//
    128     for(int i=1,l,r,ans=0;i<=q;i++){
    129         l=rd();r=rd();
    130         if(typ)l^=ans,r^=ans;
    131         ans = n - query(rt[r],1,m,l,r);
    132         printf("%d
    ",ans);
    133     }//
    134     return 0;
    135 }//by tkys_Austin;
    136 
    View Code

     

  • 相关阅读:
    MVC通过后台注解来添加对数据的验证。
    HTML赋值方法练习
    HTML辅助方法的练习一
    第一次接触MVC Models概念
    部分视图的理解
    使用布局文件(Layout)
    springboot基本配置及快速启动
    springboot代码测试注意事项
    logback日志的基本使用
    springboot快速创建项目框架
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/9795802.html
Copyright © 2020-2023  润新知