zoukankan      html  css  js  c++  java
  • bzoj3514 Codechef MARCH14 GERALD07加强版

    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

    正解:link-cut tree+主席树。

    这题一眼看上去就不会做woc。。其实我知道一个暴力的莫队+lctO(n√nlogn)做法,不过强制在线。。

    有一个比较猎奇的做法:首先把边依次加到图中,若当前这条边与图中的边形成了环,那么把这个环中最早加进来的边弹出去
    并将每条边把哪条边弹了出去记录下来:ntr[i] = j,特别地,要是没有弹出边,ntr[i] = 0;
    这个显然是可以用LCT来弄的对吧。
    然后对于每个询问,我们的答案就是对l~r中ntr小于l的边求和,并用n减去这个值
    正确性可以YY一下:
    如果一条边的ntr >= l,那么显然他可以与从l ~ r中的边形成环,那么它对答案没有贡献
    反之如果一条边的ntr < l那么它与从l ~ r中的边是不能形成环的,那么他对答案的贡献为-1
    对于查询从l ~ r中有多少边的ntr小于l,我反正是用的函数式线段树

    ——hzwer博客

    然后还有一个特判,如果i边是自环,那nxt[i]=i,还好样例就有。。然后虽然一次AC了,这题我却写了一个多小时,LCT我都忘记写了。。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <complex>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <cstdio>
      8 #include <vector>
      9 #include <cmath>
     10 #include <queue>
     11 #include <stack>
     12 #include <map>
     13 #include <set>
     14 #define inf (1<<30)
     15 #define N (200010)
     16 #define il inline
     17 #define RG register
     18 #define ll long long
     19 #define min(a,b) (a<b ? a : b)
     20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     21 
     22 using namespace std;
     23 
     24 struct edge{ int u,v; }g[N];
     25 
     26 int sum[2*N],val[2*N],lazy[2*N],ch[2*N][2],fa[2*N],st[2*N];
     27 int s[20*N],ls[20*N],rs[20*N],rt[N],nxt[N],sz,n,m,k,type,ans;
     28 
     29 il int gi(){
     30     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     31     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
     32 }
     33 
     34 il void pushdown(RG int x){ lazy[x]=0,lazy[ch[x][0]]^=1,lazy[ch[x][1]]^=1,swap(ch[x][0],ch[x][1]); return; }
     35 
     36 il void pushup(RG int x){ 
     37     sum[x]=val[x];
     38     if (ch[x][0]) sum[x]=min(sum[x],sum[ch[x][0]]);
     39     if (ch[x][1]) sum[x]=min(sum[x],sum[ch[x][1]]);
     40     return;
     41 }
     42 
     43 il int isroot(RG int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; }
     44 
     45 il void rotate(RG int x){
     46     RG int y=fa[x],z=fa[y],k=ch[y][0]==x;
     47     if (!isroot(y)) ch[z][ch[z][1]==y]=x; fa[x]=z;
     48     ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y;
     49     ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return;
     50 }
     51 
     52 il void splay(RG int x){
     53     RG int top=0; st[++top]=x;
     54     for (RG int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
     55     for (RG int i=top;i;--i) if (lazy[st[i]]) pushdown(st[i]);
     56     while (!isroot(x)){
     57     RG int y=fa[x],z=fa[y];
     58     if (!isroot(y)){
     59         ((ch[z][0]==y)^(ch[y][0]==x)) ? rotate(x) : rotate(y);
     60     }
     61     rotate(x);
     62     }
     63     return;
     64 }
     65 
     66 il void access(RG int x){ RG int t=0; while (x) splay(x),ch[x][1]=t,pushup(x),t=x,x=fa[x]; return; }
     67 
     68 il void makeroot(RG int x){ access(x),splay(x),lazy[x]^=1; return; }
     69 
     70 il void link(RG int x,RG int y){ makeroot(x),fa[x]=y; return; }
     71 
     72 il void cut(RG int x,RG int y){ makeroot(x),access(y),splay(y),fa[x]=ch[y][0]=0; return; }
     73 
     74 il int query(RG int x,RG int y){ makeroot(x),access(y),splay(y); return sum[y]; }
     75 
     76 il int find(RG int x){ access(x),splay(x); while (ch[x][0]) x=ch[x][0]; return x; }
     77 
     78 il void insert(RG int x,RG int &y,RG int l,RG int r,RG int v){
     79     s[y=++sz]=s[x]+1,ls[y]=ls[x],rs[y]=rs[x]; if (l==r) return; RG int mid=(l+r)>>1;
     80     v<=mid ? insert(ls[x],ls[y],l,mid,v) : insert(rs[x],rs[y],mid+1,r,v); return;
     81 }
     82 
     83 il int query(RG int x,RG int y,RG int l,RG int r,RG int v){
     84     if (l==r) return 0; RG int mid=(l+r)>>1;
     85     return v<=mid ? query(ls[x],ls[y],l,mid,v) : query(rs[x],rs[y],mid+1,r,v)+s[ls[y]]-s[ls[x]];
     86 }
     87 
     88 il void work(){
     89     n=gi(),m=gi(),k=gi(),type=gi(); RG int l,r;
     90     for (RG int i=1;i<=n;++i) val[i]=inf;
     91     for (RG int i=1;i<=m;++i) val[n+i]=i;
     92     for (RG int i=1;i<=m;++i){
     93     g[i].u=gi(),g[i].v=gi();
     94     if (g[i].u==g[i].v){ nxt[i]=i; continue; }
     95     if (find(g[i].u)==find(g[i].v)){
     96         RG int res=query(g[i].u,g[i].v);
     97         nxt[i]=res,cut(g[res].u,n+res),cut(g[res].v,n+res);
     98     }
     99     link(g[i].u,n+i),link(g[i].v,n+i);
    100     }
    101     for (RG int i=1;i<=m;++i) insert(rt[i-1],rt[i],0,m,nxt[i]);
    102     for (RG int i=1;i<=k;++i){
    103     l=gi(),r=gi(); if (type) l^=ans,r^=ans;
    104     ans=n-query(rt[l-1],rt[r],0,m,l); printf("%d
    ",ans);
    105     }
    106     return;
    107 }
    108 
    109 int main(){
    110     File("graph");
    111     work();
    112     return 0;
    113 }
  • 相关阅读:
    什么是Redis?
    请写出常用的linux指令
    Maven常用命令有哪些?
    Maven的工程类型有哪些?
    Maven仓库是什么
    什么是Maven?
    Shiro 的优点
    比较 SpringSecurity 和 Shiro
    判断x二进制编码中1的个数的奇偶性
    寻找600851475143的最大素因子的快速算法
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6477782.html
Copyright © 2011-2022 走看看