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

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3514

    题目:

    3514: Codechef MARCH14 GERALD07加强版

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 1822  Solved: 703
    [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

    By zhonghaoxi

    思路:

      想了二十分钟后果断滚去看题解了。

      有一个比较猎奇的做法:首先把边依次加到图中,若当前这条边与图中的边形成了环,那么把这个环中最早加进来的边弹出去
      并将每条边把哪条边弹了出去记录下来: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,我反正是用的函数式线段树

      lct+主席树,好神啊。

      主席树开200007*20居然re,说好的nlogn呢。

      1 /**************************************************************
      2     Problem: 3514
      3     User: weeping
      4     Language: C++
      5     Result: Accepted
      6     Time:45408 ms
      7     Memory:110692 kb
      8 ****************************************************************/
      9  
     10 #include <bits/stdc++.h>
     11  
     12 using namespace std;
     13  
     14 const int K = 300007 * 20;
     15  
     16 struct Link_Cut_Tree
     17 {
     18     static const int MAXN = 500000 + 7;
     19  
     20     int ch[MAXN][2], fa[MAXN], rev[MAXN], v[MAXN], mx[MAXN] ,id[MAXN];
     21     int sk[MAXN];
     22  
     23     bool isroot(int x)
     24     {
     25         return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
     26     }
     27  
     28     void reverse(int x)
     29     {
     30         rev[x] ^= 1, swap(ch[x][0],ch[x][1]);
     31     }
     32  
     33     void update(int x)
     34     {
     35         int lc = ch[x][0], rc = ch[x][1];
     36         mx[x] = v[x], id[x] = x;
     37         if(lc&&mx[lc]<mx[x])
     38             mx[x] = mx[lc], id[x] = id[lc];
     39         if(rc&&mx[rc]<mx[x])
     40             mx[x] = mx[rc], id[x] = id[rc];
     41     }
     42  
     43     void push_down(int x)
     44     {
     45         if(!rev[x]) return ;
     46         if(ch[x][0]) reverse(ch[x][0]);
     47         if(ch[x][1]) reverse(ch[x][1]);
     48         rev[x]=0;
     49     }
     50  
     51     void rotate(int x)
     52     {
     53         int f = fa[x], gf = fa[f];
     54         int t1 = ( x != ch[f][0]), t2 = ( f != ch[gf][0]), tmp = ch[x][1^t1];
     55         if(!isroot(f)) ch[gf][0^t2] = x;
     56         fa[tmp] = f, fa[x] = gf, ch[x][1^t1] = f, fa[f] = x, ch[f][0^t1] = tmp;
     57         update(f);
     58     }
     59  
     60     void splay(int x)
     61     {
     62         int top = 0;
     63         sk[++top] = x;
     64         for(int i = x; !isroot(i); i = fa[i])   sk[++top] = fa[i];
     65         while(top)  push_down(sk[top--]);
     66         for(int f = fa[x], gf = fa[f]; !isroot(x); rotate(x), f = fa[x],gf = fa[f])
     67         if(!isroot(f))
     68             rotate((x==ch[f][0]) ^ (f==ch[gf][0]) ? x : f);
     69         update(x);
     70     }
     71  
     72     void access(int x)
     73     {
     74         for(int p = 0; x; p = x, x = fa[x])
     75             splay(x), ch[x][1] = p, update(x);
     76     }
     77  
     78     void makeroot(int x)
     79     {
     80         access(x), splay(x), reverse(x);
     81     }
     82  
     83     int findroot(int x)
     84     {
     85         access(x), splay(x);
     86         while(ch[x][0]) x = ch[x][0];
     87         return x;
     88     }
     89     void link(int x,int y)
     90     {
     91         makeroot(x), fa[x] = y;
     92     }
     93  
     94     void cut(int x,int y)
     95     {
     96         makeroot(x), access(y), splay(y);
     97         if(ch[y][0] == x)   ch[y][0] = fa[x] = 0;
     98         update(y);
     99     }
    100  
    101     int go(int u,int v,int n,int m,int k)
    102     {
    103         if(u==v)
    104             return m+2;
    105         if(findroot(u)!=findroot(v))
    106         {
    107             link(u,k+n),link(v,k+n);
    108             return 1;
    109         }
    110         makeroot(u),access(v),splay(v);
    111         int p = id[v];
    112         splay(p);
    113         fa[ch[p][0]] = fa[ch[p][1]] = 0;
    114         ch[p][0] = ch[p][1] = 0;
    115         link(u,k+n),link(v,k+n);
    116         return p-n+1;
    117     }
    118 }lct;
    119  
    120  
    121 int tot,ls[K],rs[K],rt[K],sum[K];
    122  
    123 void build(int &o,int l,int r)
    124 {
    125     o=++tot,sum[o]=0;
    126     int mid=l+r>>1;
    127     if(l!=r)
    128         build(ls[o],l,mid),build(rs[o],mid+1,r);
    129 }
    130 void update(int &o,int l,int r,int last,int x)
    131 {
    132     o=++tot,sum[o]=sum[last]+1;
    133     ls[o]=ls[last],rs[o]=rs[last];
    134     if(l==r) return ;
    135     int mid=l+r>>1;
    136     if(x<=mid) update(ls[o],l,mid,ls[last],x);
    137     else update(rs[o],mid+1,r,rs[last],x);
    138 }
    139 int query(int lo,int ro,int l,int r,int k)
    140 {
    141     if(r<=k) return sum[ro]-sum[lo];
    142     if(l>k) return 0;
    143     int mid=l+r>>1;
    144     return query(ls[lo],ls[ro],l,mid,k) + query(rs[lo],rs[ro],mid+1,r,k);
    145 }
    146  
    147 int main(void)
    148 {
    149     //freopen("in.acm","r",stdin);
    150    int n,m,k,tp;
    151    scanf("%d%d%d%d",&n,&m,&k,&tp);
    152    for(int i=1;i<=n;i++)    lct.v[i] = lct.mx[i] = m + 2, lct.id[i] = i;
    153    build(rt[0],1,m+2);
    154    for(int i=1,x,y;i<=m;i++)
    155    {
    156        scanf("%d%d",&x,&y);
    157        lct.v[i+n]=lct.mx[i+n]=i,lct.id[i+n]=i+n;
    158        update(rt[i],1,m+2,rt[i-1],lct.go(x,y,n,m,i));;
    159    }
    160    int l,r,ls=0;
    161    while(k--)
    162    {
    163        scanf("%d%d",&l,&r);
    164        if(tp)   l^=ls,r^=ls;
    165        ls=n-query(rt[l-1],rt[r],1,m+2,l);
    166        printf("%d
    ",ls);
    167    }
    168     return 0;
    169 }
  • 相关阅读:
    使用TransactionScope实现多数据库连接事务操作
    zabbix_agentlinux下的安装
    (转)Zabbix AgentWindows平台配置指导
    使用SpringSide 3.1.4.3开发Web项目的全过程(上)
    应用开发中数据字典项设计实现方案
    Oracle Top N 和 Oracle中的limit问题解决方案
    Struts 2.0的codebehinde插件应用简述
    PropertyUtils和MethodUtils使用
    Log4j基本使用方法
    Quartz从入门到进阶
  • 原文地址:https://www.cnblogs.com/weeping/p/7620179.html
Copyright © 2011-2022 走看看