USACO 2015 December Contest, Platinum Problem Max Flow【树链剖分】

  题意比较难理解,就是给你n个点的树,然后给你m个修改操作,每一次修改包括一个点对(x, y),意味着将x到y所有的点权值加一,最后问你整个树上的点权最大是多少。

  

  比较裸的树链剖分了,感谢Haild的讲解。

  首先第一遍dfs预处理出size,son(重儿子)。

  第二遍dfs重编号。

  然后线段树就可以了。

 

  感觉就是把一棵树弄成一条一条的链,新奇的hash方法。

  1 #include <bits/stdc++.h>
  2 #define rep(i, a, b) for (int i = a; i <= b; i++)
  3 #define drep(i, a, b) for (int i = a; i >= b; i--)
  4 #define REP(i, a, b) for (int i = a; i < b; i++)
  5 #define pb push_back
  6 #define mp make_pair
  7 #define clr(x) memset(x, 0, sizeof(x))
  8 #define xx first
  9 #define yy second
 10 using namespace std;
 11 typedef long long i64;
 12 typedef pair<int, int> pii;
 13 const int inf = ~0U >> 1;
 14 const i64 INF = ~0ULL >> 1;
 15 //*******************************
 16 
 17 template <typename T> void MAX(T &a, T &b) { if (a < b) a = b; }
 18 template <typename T> void MIN(T &a, T &b) { if (a > b) a = b; }
 19 
 20 const int maxn = 50005;
 21 
 22 struct Ed {
 23     int u, v, nx; Ed() {}
 24     Ed(int _u, int _v, int _nx) :
 25         u(_u), v(_v), nx(_nx) {}
 26 } E[maxn << 1];
 27 int G[maxn], edtot;
 28 void addedge(int u, int v) {
 29     E[++edtot] = Ed(u, v, G[u]);
 30     G[u] = edtot;
 31     E[++edtot] = Ed(v, u, G[v]);
 32     G[v] = edtot;
 33 }
 34 
 35 struct Seg_Tree {
 36     int lazy[maxn << 2], Max[maxn << 2];
 37     void Push_down(int o) {
 38         if (!lazy[o]) return;
 39         lazy[o << 1] += lazy[o], lazy[o << 1 | 1] += lazy[o];
 40         Max[o << 1] += lazy[o], Max[o << 1 | 1] += lazy[o];
 41         lazy[o] = 0;
 42     }
 43     void Push_up(int o) { Max[o] = max(Max[o << 1], Max[o << 1 | 1]); }
 44     void update(int o, int l, int r, int ql, int qr, int v) {
 45         if (ql <= l && r <= qr) {
 46             lazy[o] += v;
 47             Max[o] += v;
 48             return;
 49         }
 50         Push_down(o);
 51         int mid = l + r >> 1;
 52         if (ql <= mid) update(o << 1, l, mid, ql, qr, v);
 53         if (qr > mid) update(o << 1 | 1, mid + 1, r, ql, qr, v);
 54         Push_up(o);
 55     }
 56 } T;
 57 
 58 int size[maxn], pre[maxn], son[maxn], dep[maxn];
 59 int dfs_size(int x, int fa) {
 60     size[x] = 1; int haha = -inf; pre[x] = fa; dep[x] = dep[fa] + 1;
 61     for (int i = G[x]; i; i = E[i].nx) if (E[i].v != fa) {
 62         size[x] += dfs_size(E[i].v, x);
 63         if (size[E[i].v] > haha) haha = size[E[i].v], son[x] = E[i].v;
 64     }
 65     return size[x];
 66 }
 67 int ndtot, pos[maxn], top[maxn];
 68 void repos(int x, int tp) {
 69     pos[x] = ++ndtot;
 70     top[x] = tp;
 71     if (son[x]) repos(son[x], tp);
 72     for (int i = G[x]; i; i = E[i].nx) if (E[i].v != pre[x] && E[i].v != son[x]) repos(E[i].v, E[i].v);
 73 }
 74 
 75 int n;
 76 void update(int x, int y) {
 77     while (top[x] != top[y]) {
 78         if (dep[top[x]] < dep[top[y]]) swap(x, y);
 79         T.update(1, 1, n, pos[top[x]], pos[x], 1); x = pre[top[x]];
 80     }
 81     T.update(1, 1, n, min(pos[x], pos[y]), max(pos[x], pos[y]), 1);
 82 }
 83 
 84 int main() {
 85     freopen("maxflow.in", "r", stdin);
 86     freopen("maxflow.out", "w", stdout);
 87     int m; scanf("%d%d", &n, &m);
 88     REP(i, 1, n) {
 89         int x, y; scanf("%d%d", &x, &y);
 90         addedge(x, y);
 91     }
 92     dfs_size(1, 1);
 93     repos(1, 1);
 94     while (m--) {
 95         int x, y; scanf("%d%d", &x, &y);
 96         update(x, y);
 97     }
 98     printf("%d\n", T.Max[1]);
 99     return 0;
100 }
View Code

 

转载于:https://www.cnblogs.com/y7070/p/5066253.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值