1. 程式人生 > >bzoj 2001 CITY 城市建設 cdq分治

bzoj 2001 CITY 城市建設 cdq分治

題目傳送門

題解:

對整個修改的區間進行分治。對於當前修改區間來說,我們對整幅圖中將要修改的邊權都先改成-inf,跑一遍最小生成樹,然後對於一條樹邊並且他的權值不為-inf,那麼這條邊一定就是樹邊了。然後我們把這些點都縮成一個點。然後,我們繼續對當前修改區間來說,我們把要修改的邊的邊權都修改成inf,跑一遍最小生成樹,然後對於一條非樹邊來說,他的邊權不為inf,那麼這條邊一點是非樹邊了,然後我們每層縮點,減邊,這樣圖就會越來越小,然後當l == r的時候,我們還原修改操作,最後把跑最小生成樹計算答案。

一道神奇的cdq題目。

程式碼:

  1 #include<bits/stdc++.h>
  2
using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define
lch(x) tr[x].son[0] 12 #define rch(x) tr[x].son[1] 13 #define max3(a,b,c) max(a,max(b,c)) 14 #define min3(a,b,c) min(a,min(b,c)) 15 typedef pair<int,int> pll; 16 const int inf = 0x3f3f3f3f; 17 const LL INF = 0x3f3f3f3f3f3f3f3f; 18 const LL mod = (int)1e9+7; 19 const int N = 1e5 + 100; 20 struct
Node{ 21 int u, v, c, id; 22 bool operator < (const Node & x) const{ 23 return c < x.c; 24 } 25 }e[20][N], f[N], g[N]; 26 int a[N], b[N], ct[N], mapid[N]; 27 int pre[N]; 28 int Find(int x){ 29 if(x == pre[x]) return x; 30 return pre[x] = Find(pre[x]); 31 } 32 LL ans[N]; 33 void Clear(int tot){ 34 for(int i = 1; i <= tot; i++){ 35 pre[f[i].u] = f[i].u; 36 pre[f[i].v] = f[i].v; 37 } 38 } 39 void contraction(int &tot, LL &sum){ 40 Clear(tot); 41 sort(f+1, f+1+tot); 42 int u, v, zz = 0; 43 for(int i = 1; i <= tot; i++){ 44 u = Find(f[i].u), v = Find(f[i].v); 45 if(u != v){ 46 pre[u] = v; 47 if(f[i].c != -inf){ 48 sum += f[i].c; 49 g[++zz] = f[i]; 50 } 51 } 52 } 53 Clear(tot); 54 for(int i = 1; i <= zz; i++){ 55 u = Find(g[i].u); v = Find(g[i].v); 56 pre[u] = v; 57 } 58 zz = 0; 59 for(int i = 1; i <= tot; i++){ 60 u = Find(f[i].u), v = Find(f[i].v); 61 if(u != v){ 62 f[++zz] = f[i]; 63 f[zz].u = u; 64 f[zz].v = v; 65 mapid[f[i].id] = zz; 66 } 67 } 68 tot = zz; 69 return ; 70 } 71 void reduction(int &tot){ 72 Clear(tot); 73 sort(f+1, f+1+tot); 74 int u, v, zz = 0; 75 for(int i = 1; i <= tot; i++){ 76 u = Find(f[i].u); v = Find(f[i].v); 77 if(u != v){ 78 pre[u] = v; 79 f[++zz] = f[i]; 80 } 81 else if(f[i].c == inf) 82 f[++zz] = f[i] 83 } 84 tot = zz; 85 return ; 86 } 87 void cdq(int l, int r, int now, int tot, LL sum){ 88 if(l == r) ct[a[l]] = b[l]; 89 for(int i = 1; i <= tot; i++){ 90 e[now][i].c = ct[e[now][i].id]; 91 mapid[e[now][i].id] = i; 92 f[i] = e[now][i]; 93 } 94 if(l == r){ 95 ans[l] = sum; 96 Clear(tot); 97 sort(f+1, f+1+tot); 98 int u, v; 99 for(int i = 1; i <= tot; i++){ 100 u = Find(f[i].u), v = Find(f[i].v); 101 if(u != v){ 102 pre[u] = v; 103 ans[l] += f[i].c; 104 } 105 } 106 return ; 107 } 108 for(int i = l; i <= r; i++) f[mapid[a[i]]].c = -inf; 109 contraction(tot, sum); 110 for(int i = l; i <= r; i++) f[mapid[a[i]]].c = inf; 111 reduction(tot); 112 for(int i = 1; i <= tot; i++) e[now+1][i] = f[i]; 113 int mid = l+r >> 1; 114 cdq(l, mid, now+1, tot, sum); 115 cdq(mid+1, r, now+1, tot, sum); 116 117 } 118 int main(){ 119 int n, m, q; 120 scanf("%d%d%d", &n, &m, &q); 121 for(int i = 1; i <= m; i++){ 122 scanf("%d%d%d", &e[0][i].u, &e[0][i].v, &e[0][i].c); 123 e[0][i].id = i; 124 ct[i] = e[0][i].c; 125 } 126 for(int i = 1; i <= q; i++) 127 scanf("%d%d", &a[i], &b[i]); 128 cdq(1,q,0,m,0); 129 for(int i = 1; i <= q; ++i) 130 printf("%lld\n", ans[i]); 131 return 0; 132 }
View Code