1. 程式人生 > >bzoj3514: Codechef MARCH14 GERALD07加強版

bzoj3514: Codechef MARCH14 GERALD07加強版

open 十分 acc access %20 out script 整數 100%

地址: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\n",ls);
167    }
168     return 0;
169 }

bzoj3514: Codechef MARCH14 GERALD07加強版