zoukankan      html  css  js  c++  java
  • [CodeChef

    Read problems statements in Mandarin Chinese and Russian.

    Problem Statement

    Chef has a undirected graph G. This graph consists of N vertices and M edges. Each vertex of the graph has an unique index from 1 to N, also each edge of the graph has an unique index from 1 to M.

    Also Chef has Q pairs of integers: LiRi (1 ≤ Li ≤ Ri ≤ M). For each pair LiRi, Chef wants to know: how many connected components will contain graph G if Chef erase all the edges from the graph, except the edges with indies X, where Li ≤ X ≤ Ri. Please, help Chef with these queries.

    Input

    The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
    The first line of each test case contains three integers NMQ. Each of the next M lines contains a pair of integers ViUi - the current edge of graph G. Each of the next Q lines contains a pair of integers LiRi - the current query.

    Output

    For each query of each test case print the required number of connected components.

    Constraints

    • 1 ≤ T ≤ 1000.
    • 1 ≤ NMQ ≤ 200000.
    • 1 ≤ UiVi ≤ N.
    • 1 ≤ Li ≤ Ri ≤ M.
    • Sum of all values of N for test cases is not greater than 200000. Sum of all values of M for test cases is not greater than 200000. Sum of all values of Q for test cases is not greater than 200000.
    • Graph G can contain self-loops and multiple edges.

    Example

    Input:
    2
    3 5 4
    1 3
    1 2
    2 1
    3 2
    2 2
    2 3
    1 5
    5 5
    1 2
    1 1 1
    1 1
    1 1
    Output:
    2
    1
    3
    1
    1

    破题坑了一晚上

    题目大意?见上面超链接的中文题面。

    树 LCT 动态维护生成树

    将所有询问按右端点递增顺序排序,从1到m依次加边。

    用LCT维护当前的生成树,生成树中保留的是编号尽量大的边。

    同时用线段树维护生成树中保留了哪些边(权值线段树,存编号)。

    查询时,在线段树上查询$[L,R]$范围内有多少条边,若查询结果为$ x $,则连通块数为$n-x$

    注意有自环和重边,这使得维护生成树的时候不能一律删编号最靠前的边,而要先查询生成树中有没有重边。

    细节蛮多的。

    注意多组数据,初始化结点的时候要初始化到n+m

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #define LL long long
      7 using namespace std;
      8 const int INF=0x3f3f3f3f;
      9 const int mxn=420010;
     10 int read(){
     11     int x=0,f=1;char ch=getchar();
     12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     14     return x*f;
     15 }
     16 struct edge{
     17     int x,y;
     18 }e[mxn];
     19 struct query{
     20     int L,R;
     21     int id;
     22     bool operator < (const query &b)const{
     23         return R<b.R;
     24     }
     25 }q[mxn];
     26 int ans[mxn];
     27 //
     28 struct SGT{
     29     int smm[mxn<<2];
     30     #define ls rt<<1
     31     #define rs rt<<1|1
     32     void clear(int ed){
     33         ed=ed<<2;
     34         for(register int i=0;i<=ed;i++)smm[i]=0;
     35     }
     36     void pushup(int rt){smm[rt]=smm[ls]+smm[rs];return;}
     37     void update(int p,int v,int l,int r,int rt){
     38         if(l==r){
     39             smm[rt]+=v;
     40             return;
     41         }
     42         int mid=(l+r)>>1;
     43         if(p<=mid)update(p,v,l,mid,ls);
     44         else update(p,v,mid+1,r,rs);
     45         pushup(rt);
     46         return;
     47     }
     48     int query(int L,int R,int l,int r,int rt){
     49         if(L<=l && r<=R){
     50             return smm[rt];
     51         }
     52         int mid=(l+r)>>1;
     53         if(R<=mid)return query(L,R,l,mid,ls);
     54         if(L>mid)return query(L,R,mid+1,r,rs);
     55         return query(L,R,l,mid,ls)+query(L,R,mid+1,r,rs);
     56     }
     57     #undef ls
     58     #undef rs
     59 }SG;
     60 int n,m,Q;
     61 //
     62 struct node{
     63     int ch[2],fa;
     64     int val,mn,minpos;
     65     bool rev;
     66 }t[mxn];
     67 int cnt=0;
     68 void rever(int x){
     69     int &lc=t[x].ch[0],&rc=t[x].ch[1];
     70     swap(lc,rc);
     71     t[lc].rev^=1;t[rc].rev^=1;
     72     return;
     73 }
     74 void PD(int x){
     75     if(t[x].rev){
     76         rever(x);
     77         t[x].rev=0;
     78     }
     79     return;
     80 }
     81 void pushup(int x){
     82     int lc=t[x].ch[0],rc=t[x].ch[1];
     83     t[x].mn=t[x].val;t[x].minpos=x;
     84     if(t[lc].mn<t[x].mn){
     85         t[x].mn=t[lc].mn; t[x].minpos=t[lc].minpos;
     86     }
     87     if(t[rc].mn<t[x].mn){
     88         t[x].mn=t[rc].mn; t[x].minpos=t[rc].minpos;
     89     }
     90     return;
     91 }
     92 inline bool isroot(int x){
     93     return (t[t[x].fa].ch[0]^x)&&(t[t[x].fa].ch[1]^x);
     94 }
     95 void rotate(int x){
     96     int y=t[x].fa,z=t[y].fa,lc,rc;
     97     if(t[y].ch[0]==x)lc=0;else lc=1;rc=lc^1;
     98     if(!isroot(y)){
     99         t[z].ch[t[z].ch[1]==y]=x;
    100     }
    101     t[x].fa=z;t[y].fa=x;
    102     t[t[x].ch[rc]].fa=y;
    103     t[y].ch[lc]=t[x].ch[rc];
    104     t[x].ch[rc]=y;
    105     pushup(y);
    106     return;
    107 }
    108 int st[mxn],top=0;
    109 void Splay(int x){
    110     st[top=1]=x;
    111     for(int i=x;t[i].fa;i=t[i].fa){
    112         st[++top]=t[i].fa;
    113     }
    114     while(top)PD(st[top--]);
    115     while(!isroot(x)){
    116         int y=t[x].fa,z=t[y].fa;
    117         if(!isroot(y)){
    118             if((t[y].ch[0]==x)^(t[z].ch[0]==y))rotate(x);
    119                 else rotate(y);
    120         }
    121         rotate(x);
    122     }
    123     pushup(x);
    124     return;
    125 }
    126 //
    127 void access(int x){
    128     for(int y=0;x;x=t[x].fa){
    129         Splay(x);
    130         t[x].ch[1]=y;
    131         pushup(x);
    132         y=x;
    133     }
    134     return;
    135 }
    136 int find(int x){
    137     access(x);Splay(x);
    138     while(t[x].ch[0]){
    139         x=t[x].ch[0];
    140     }
    141     return x;
    142 }
    143 void mkroot(int x){
    144     access(x);Splay(x);
    145     t[x].rev^=1;
    146     return;
    147 }
    148 void link(int x,int y){
    149     mkroot(x); t[x].fa=y;
    150     return;
    151 }
    152 void cut(int x,int y){
    153     mkroot(x);
    154     access(y);Splay(y);
    155     if(t[y].ch[0]==x){t[x].fa=0;t[y].ch[0]=0;}
    156     pushup(y);
    157     return;
    158 }
    159 //
    160 void solve(){
    161     int hd=1;
    162     cnt=n;
    163     for(int i=1;i<=m;i++){//按序加边
    164         int x=e[i].x,y=e[i].y;
    165         if(x!=y && find(x)==find(y)){
    166             bool flag=0;
    167             mkroot(x);access(y);Splay(y);
    168             //
    169 /*            printf("-----
    ");
    170             for(int j=1;j<=cnt;j++){
    171                 printf("#%d: lc:%d rc:%d fa:%d
    ",j,t[j].ch[0],t[j].ch[1],t[j].fa);
    172             }
    173             printf("-----
    ");*/
    174             //
    175             int res=t[y].ch[0];
    176             while(t[res].ch[1])res=t[res].ch[1];
    177             res=res-n;
    178             if(res>0 && e[res].x==x && e[res].y==y){
    179                 flag=1;
    180                 cut(x,res+n);
    181                 cut(y,res+n);
    182                 SG.update(res,-1,1,m,1);
    183             }
    184             //
    185             if(!flag){
    186                 mkroot(x);access(y);Splay(y);
    187                 int tar=t[y].minpos;
    188                 cut(e[tar-n].x,tar);
    189                 cut(e[tar-n].y,tar);
    190                 SG.update(tar-n,-1,1,m,1);
    191             }
    192         }
    193         ++cnt;
    194         if(x!=y){
    195             t[cnt].val=t[cnt].mn=i;
    196             t[cnt].minpos=cnt;
    197             link(x,cnt);
    198             link(cnt,y);
    199             SG.update(i,1,1,m,1);
    200         }
    201         while(hd<=Q && q[hd].R<=i){
    202             if(q[hd].R==i){
    203                 ans[q[hd].id]=n-SG.query(q[hd].L,q[hd].R,1,m,1);
    204             }
    205             hd++;
    206         }
    207     }
    208     return;
    209 }
    210 void init(int n,int m){
    211     int ed=n+m;
    212     t[0].minpos=0;t[0].mn=INF;
    213     for(register int x=1;x<=ed;x++){
    214         t[x].ch[0]=t[x].ch[1]=t[x].fa=0;
    215         t[x].minpos=0;t[x].mn=INF;
    216         t[x].val=INF;
    217         t[x].rev=0;
    218     }
    219     SG.clear(ed);
    220     return;
    221 }
    222 int main(){
    223 //    freopen("in.txt","r",stdin);
    224     int i;
    225     int T=read();
    226     while(T--){
    227         n=read();m=read();Q=read();
    228         init(n,m);
    229         for(i=1;i<=m;i++){
    230             e[i].x=read();e[i].y=read();
    231             if(e[i].x>e[i].y)swap(e[i].x,e[i].y);
    232         }
    233         for(i=1;i<=Q;i++){
    234             q[i].L=read();q[i].R=read();
    235             q[i].id=i;
    236         }
    237         sort(q+1,q+Q+1);
    238         solve();
    239         for(i=1;i<=Q;i++){
    240             printf("%d
    ",ans[i]);
    241         }
    242     }
    243     return 0;
    244 }
  • 相关阅读:
    config Doku wiki
    [转载]【python】ipython与python的区别
    数组和指针
    C++初始化数据成员
    RSA算法原理
    C++四种cast
    百度笔试准备2
    百度笔试准备1
    百度面试准备
    C++的空类中默认产生哪些类成员函数
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/7056789.html
Copyright © 2011-2022 走看看