bzoj3514: Codechef MARCH14 GERALD07加強版
阿新 • • 發佈:2017-10-02
open 十分 acc access %20 out script 整數 100%
Submit: 1822 Solved: 703
[Submit][Status][Discuss]
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
1
3
1
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3514
題目:
3514: Codechef MARCH14 GERALD07加強版
Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 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 01 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
Sample Output
21
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加強版