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 to[N];
 29 void link(int u, int v){
 30     mapid[to[v]] = 0;
 31     mapid[u] = v;
 32     to[v] = u;
 33 }
 34 int Find(int x){
 35     if(x == pre[x]) return x;
 36     return pre[x] = Find(pre[x]);
 37 }
 38 LL ans[N];
 39 void Clear(int tot){
 40     for(int i = 1; i <= tot; i++){
 41         pre[f[i].u] = f[i].u;
 42         pre[f[i].v] = f[i].v;
 43     }
 44 }
 45 void contraction(int &tot, LL &sum){
 46     Clear(tot);
 47     sort(f+1, f+1+tot);
 48     int u, v, zz = 0;
 49     for(int i = 1; i <= tot; i++){
 50         u = Find(f[i].u), v = Find(f[i].v);
 51         if(u != v){
 52             pre[u] = v;
 53             if(f[i].c != -inf){
 54                 sum += f[i].c;
 55                 g[++zz] = f[i];
 56             }
 57         }
 58     }
 59     Clear(tot);
 60     for(int i = 1; i <= zz; i++){
 61         u = Find(g[i].u); v = Find(g[i].v);
 62         pre[u] = v;
 63     }
 64     zz = 0;
 65     for(int i = 1; i <= tot; i++){
 66         u = Find(f[i].u), v = Find(f[i].v);
 67         if(u != v){
 68             f[++zz] = f[i];
 69             f[zz].u = u;
 70             f[zz].v = v;
 71             mapid[f[i].id] = zz;
 72         }
 73     }
 74     tot = zz;
 75     return ;
 76 }
 77 void reduction(int &tot){
 78     Clear(tot);
 79     sort(f+1, f+1+tot);
 80     int u, v, zz = 0;
 81     for(int i = 1; i <= tot; i++){
 82         u = Find(f[i].u); v = Find(f[i].v);
 83         if(u != v){
 84             pre[u] = v;
 85             f[++zz] = f[i];
 86         }
 87         else if(f[i].c == inf)
 88             f[++zz] = f[i];
 89     }
 90     tot = zz;
 91     return ;
 92 }
 93 void cdq(int l, int r, int now, int tot, LL sum){
 94     if(l == r) ct[a[l]] = b[l];
 95     for(int i = 1; i <= tot; i++){
 96         e[now][i].c = ct[e[now][i].id];
 97         mapid[e[now][i].id] = i;
 98         //link(e[now][i])
 99         f[i] = e[now][i];
100     }
101     if(l == r){
102         ans[l] = sum;
103         Clear(tot);
104         sort(f+1, f+1+tot);
105         int u, v;
106         for(int i = 1; i <= tot; i++){
107             u = Find(f[i].u), v = Find(f[i].v);
108             if(u != v){
109                 pre[u] = v;
110                 ans[l] += f[i].c;
111             }
112         }
113         return ;
114     }
115     for(int i = l; i <= r; i++) f[mapid[a[i]]].c = -inf;
116     contraction(tot, sum);
117     for(int i = l; i <= r; i++) f[mapid[a[i]]].c = inf;
118     reduction(tot);
119     for(int i = 1; i <= tot; i++) e[now+1][i] = f[i];
120     int mid = l+r >> 1;
121     cdq(l, mid, now+1, tot, sum);
122     cdq(mid+1, r, now+1, tot, sum);
123 
124 }
125 int main(){
126     int n, m, q;
127     scanf("%d%d%d", &n, &m, &q);
128     for(int i = 1; i <= m; i++){
129         scanf("%d%d%d", &e[0][i].u, &e[0][i].v, &e[0][i].c);
130         e[0][i].id = i;
131         ct[i] = e[0][i].c;
132     }
133     for(int i = 1; i <= q; i++)
134         scanf("%d%d", &a[i], &b[i]);
135     cdq(1,q,0,m,0);
136     for(int i = 1; i <= q; ++i)
137         printf("%lld\n", ans[i]);
138     return 0;
139 }
View Code

 

posted @ 2018-10-15 16:11  Schenker  阅读(241)  评论(0编辑  收藏  举报