BZOJ4046 [Cerc2014] Pork barre

我们把边按权值从大到小依次加入图中

如果加到边权$V$,则当前的最小生成森林中边权$v\in[V, V']$(其中$V'$是任意值)形成的森林的边权和就是对于询问$[V, V']$的答案

由于点数不多,所以可以每次暴力$dfs$找环上最大边以及暴力删除。。。

又由于是强制在线,于是用可持久化线段树维护不同权值的出现次数即可

 

  1 /**************************************************************
  2     Problem: 4046
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:8788 ms
  7     Memory:46132 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <algorithm>
 13  
 14 using namespace std;
 15 const int N = 1e3 + 5;
 16 const int M = 1e5 + 5;
 17 const int maxV = 1e6 + 5;
 18  
 19 int read();
 20  
 21 struct Edge {
 22     int x, y, v;
 23      
 24     inline bool operator < (const Edge &e) const {
 25         return v > e.v;
 26     }
 27      
 28     inline void get() {
 29         x = read(), y = read(), v = read();
 30     }
 31 } E[M];
 32  
 33 struct edge {
 34     int next, to, v;
 35     edge() {}
 36     edge(int _n, int _t, int _v) : next(_n), to(_t), v(_v) {}
 37 } e[M << 1];
 38  
 39 struct chair_tree {
 40     chair_tree *ls, *rs;
 41     int sum;
 42      
 43     #define Cnt 3500000
 44     inline void* operator new(size_t, chair_tree *_c = NULL, int f = 0) {
 45         static chair_tree mempool[Cnt], *c;
 46         if (f) c = mempool;
 47         if (_c == NULL)
 48             c -> ls = c -> rs = NULL, c -> sum = 0;
 49         else *c = *_c;
 50         return c++;
 51     }
 52     #undef Cnt
 53      
 54     #define mid (l + r >> 1)
 55     void modify(int l, int r, int pos, int d) {
 56         sum += d;
 57         if (l == r) return;
 58         if (pos <= mid) {
 59             ls = new(ls)chair_tree;
 60             ls -> modify(l, mid, pos, d);
 61         } else {
 62             rs = new(rs)chair_tree;
 63             rs -> modify(mid + 1, r, pos, d);
 64         }
 65     }
 66      
 67     int query(int l, int r, int L, int R) {
 68         if (L <= l && r <= R) return sum;
 69         int res = 0;
 70         if (ls && L <= mid) res += ls -> query(l, mid, L, R);
 71         if (rs && mid < R) res += rs -> query(mid + 1, r, L, R);
 72         return res;
 73     }
 74     #undef mid
 75 } *root[M];
 76  
 77 int n, m, ans;
 78 int first[N], tot;
 79 int fa[N];
 80 int tmp[M], len;
 81  
 82 inline void Add_Edges(int x, int y, int v) {
 83     e[++tot] = edge(first[x], y, v), first[x] = tot;
 84     e[++tot] = edge(first[y], x, v), first[y] = tot;
 85 }
 86  
 87 #define y e[x].to
 88 inline void Delete_Edge(int p, int q) {
 89     int x;
 90     if (e[first[p]].to == q) {
 91         first[p] = e[first[p]].next;
 92         return;
 93     }
 94     for (x = first[p]; x; x = e[x].next)
 95         if (e[e[x].next].to == q) {
 96             e[x].next = e[e[x].next].next;
 97             return;
 98         }
 99 }
100  
101 inline void Delete_Edges(int p, int q) {
102     Delete_Edge(p, q);
103     Delete_Edge(q, p);
104 }
105  
106 int find_max(int p, int fa, int tar) {
107     int x, tmp;
108     for (x = first[p]; x; x = e[x].next)
109         if (y != fa) {
110             if (y == tar) return x;
111             tmp = find_max(y, p, tar);
112             if (tmp != -1) {
113                 if (e[tmp].v > e[x].v) return tmp;
114                 return x;
115             }
116         }
117     return -1;
118 }
119 #undef y
120  
121 int find(int x) {
122     return fa[x] == x ? x : fa[x] = find(fa[x]);
123 }
124  
125 inline int get(int x) {
126     return lower_bound(tmp + 1, tmp + len + 1, x) - tmp;
127 }
128  
129 int main() {
130     int T, now, i, x, y, Q;
131     for (T = read(); T; --T) {
132         n = read(), m = read(), ans = 0;
133         for (i = 1; i <= n; ++i) fa[i] = i;
134         for (i = 1; i <= m; ++i) {
135             E[i].get();
136             tmp[i] = E[i].v;
137         }
138         sort(E + 1, E + m + 1);
139         sort(tmp + 1, tmp + m + 1), len = unique(tmp + 1, tmp + m + 1) - tmp - 1;
140         memset(first, 0, sizeof(first)), tot = 1;
141          
142         root[len + 1] = new(NULL, 1)chair_tree;
143         for (now = len, i = 1; now; --now) {
144             root[now] = new(root[now + 1])chair_tree;
145             for (; E[i].v == tmp[now] && i <= m; ++i) {
146                 x = find(E[i].x), y = find(E[i].y);
147                 if (x != y) fa[x] = y;
148                 else {
149                     x = find_max(E[i].x, 0, E[i].y);
150                     Delete_Edges(e[x].to, e[x ^ 1].to);
151                     root[now] -> modify(1, len, get(e[x].v), -e[x].v);
152                 }
153                 Add_Edges(E[i].x, E[i].y, E[i].v);
154                 root[now] -> modify(1, len, get(E[i].v), E[i].v);
155             }
156         }
157         for (Q = read(); Q; --Q) {
158             x = read(), y = read();
159             x = upper_bound(tmp + 1, tmp + len + 1, x - ans - 1) - tmp;
160             y = upper_bound(tmp + 1, tmp + len + 1, y - ans) - tmp - 1;
161             if (x > y) printf("%d\n", ans = 0);
162             else printf("%d\n", ans = root[x] -> query(1, len, x, y));
163         }
164     }
165     return 0;
166 }
167  
168 inline int read() {
169     static int x;
170     static char ch;
171     x = 0, ch = getchar();
172     while (ch < '0' || '9' < ch)
173         ch = getchar();
174     while ('0' <= ch && ch <= '9') {
175         x = x * 10 + ch - '0';
176         ch = getchar();
177     }
178     return x;
179 }
View Code

 

转载于:https://www.cnblogs.com/rausen/p/4528842.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值