SPOJ QTREE4 Query on a tree IV (边分治 + 堆)
来源:互联网 发布:淘宝首页轮播图片尺寸 编辑:程序博客网 时间:2024/06/03 21:17
题意:
给定一棵树,节点有黑白两种颜色,有正负的边权。
有两种操作:
一种是修改反转某个节点的颜色;
另一种是询问树上最远的两个白色节点的距离。
思路:
树剖+堆维护的代码还是没敢去码。。以后再补了。。
这里用边分治+堆来维护。
边分治的优点比起点分支来说,优点就是每次分治之后,只有两个分支,处理起来比较简单,代码比较好写。缺点就是需要添加虚点,常数比较大。
边分治就是先添加虚点,使得每个节点的度数小于等于3,添加虚点的方法很容易看懂。
边分治就是选在当前分治结构里面选一条边,使得边的两端最大联通块尽可能的小。
对于一个分治结构,假设找到的分治的边为x-y,对于这个分治结构中的路径只有两种,不经过边x-y的和经过边x-y的,前者由子分治结构来考虑,现在只考虑后者。可以对边x-y两端分别维护两个大顶堆,堆里面放的是白色节点距离x的距离或者白色节点距离y的距离。所以经过x-y的最大路径就是两个堆的最大值加上x-y的边权。但是有修改操作,我们可以在堆里面再维护一个值,就是节点号x,如果堆顶的节点是黑色的话,说明这个节点已经不能用了,要pop掉。所以对每个节点要维护它所在的每一个分治结构,并且记录它是在分支结构的哪一边,更新的时候要沿着分治结构自底向上更新,最后询问的时候就是O(1),更新是O(lognlogn)。
#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<cmath>#include<queue>#include<set>#include<algorithm>using namespace std;#define LL long long#define eps 1e-8#define MP make_pair#define N 200020#define M 400020#define NLGN 400002#pragma comment(linker, "/STACK:1024000000,1024000000")#define ls (i << 1)#define rs (ls | 1)#define md ((ll + rr) >> 1)#define lson ll, md, ls#define rson md + 1, rr, rs#define mod 258280327#define inf 0x3f3f3f3f#define pii pair<int, int>#define ULL unsigned long longint readint() { char c; while((c = getchar()) && !(c >= '0' && c <= '9') && c != '-'); int ret = c - '0', sgn = 0; if(c == '-') sgn = 1, ret = 0; while((c = getchar()) && c >= '0' && c <= '9') ret = ret * 10 + c - '0'; if(sgn) ret = -ret; return ret;}char buf[8000000],*pt = buf,*o = buf;int getint(){ int f = 1,x = 0; while((*pt != '-') && (*pt < '0' || *pt > '9')) pt ++; if(*pt == '-') f = -1,pt ++; else x = *pt++ - 48; while(*pt >= '0' && *pt <= '9') x = x * 10 + *pt ++ - 48; return x * f;}char getch(){ char ch; while(*pt < 'A' || *pt > 'Z') pt ++; ch=*pt;pt++; return ch;}struct node { int x, v; node() {} node(int x, int v):x(x), v(v) {}; bool operator < (const node &b) const { return v < b.v; }};struct P { int p, t, d; P() {} P(int p, int t, int d): p(p), t(t), d(d) {}};vector<P> vt[N];vector<node> g[N];int n, fst[N], nxt[M], vv[M], cost[M], e;bool del[M];int tot, cnt, sz[N];void init() { memset(fst, -1, sizeof fst); e = 0;}void add(int u, int v, int c) { del[e] = 0, vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++; del[e] = 0, vv[e] = u, nxt[e] = fst[v], cost[e] = c, fst[v] = e++;}vector<node> t;int mx[NLGN], cc[NLGN], LC[NLGN], RC[NLGN];priority_queue<node> q[NLGN][2];priority_queue<node> Q;int ans;bool col[N];void dfs(int u, int p) {int fa = 0; for(int i = 0; i < g[u].size(); ++i) { int v = g[u][i].x; if(v == p) continue;if(fa == 0) {add(u, v, g[u][i].v);fa = u;}else {int k = ++tot;add(fa, k, 0);add(k, v, g[u][i].v);fa = k;} dfs(v, u); }}void dfs1(int u, int p) { sz[u] = 1; for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; if(v == p || del[i]) continue; dfs1(v, u); sz[u] += sz[v]; }}pii dfs2(int u, int p, int tt) { pii ret(inf, -1); for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; if(v == p || del[i]) continue; int x = max(sz[v], tt - sz[v]); if(x < ret.first) ret = MP(x, i); pii t = dfs2(v, u, tt); if(t.first < ret.first) ret = t; } return ret;}void dfs3(int u, int p, int k, int t, int d) { if(u >= 1 && u <= n) { vt[u].push_back(P(k, t, d)); q[k][t].push(node(u, d)); } for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i], c = cost[i]; if(v == p || del[i]) continue; dfs3(v, u, k, t, d + c); }}void update(int p) { while(!q[p][0].empty()) { if(col[q[p][0].top().x]) { q[p][0].pop(); continue; } break; } while(!q[p][1].empty()) { if(col[q[p][1].top().x]) { q[p][1].pop(); continue; } break; }if(q[p][0].empty() || q[p][1].empty())mx[p] = 0;elsemx[p] = q[p][0].top().v + q[p][1].top().v + cc[p];if(LC[p]) mx[p] = max(mx[p], mx[LC[p]]);if(LC[p]) mx[p] = max(mx[p], mx[RC[p]]);}int calc(int u) { dfs1(u, -1); int id = dfs2(u, -1, sz[u]).second; if(id == -1) return 0; int x = vv[id], y = vv[id^1]; del[id] = del[id^1] = 1; int t = ++cnt; dfs3(x, -1, t, 0, 0); dfs3(y, -1, t, 1, 0); LC[t] = calc(x);RC[t] = calc(y); cc[t] = cost[id]; ans = max(ans, mx[t]); update(t);return t;}int main() { // freopen("tt.txt", "r", stdin); fread(buf,1,8000000,stdin); while(1) { n = getint(); init(); for(int i = 1; i < n; ++i) { int u, v, c; u = getint(); v = getint(); c = getint(); g[u].push_back(node(v, c)); g[v].push_back(node(u, c)); } tot = n; dfs(1, -1); ans = 0; calc(1); int qq; qq = getint(); int node_cnt = n; while(qq--) { char s[10]; int u; s[0] = getch(); if(s[0] == 'A') { if(node_cnt == 0) { puts("They have disappeared."); } else printf("%d\n", max(0, mx[1])); continue; } u = getint(); if(col[u]) { ++node_cnt; col[u] = 0; for(int i = vt[u].size() - 1; i >= 0; --i) { int p = vt[u][i].p; int t = vt[u][i].t; int d = vt[u][i].d; q[p][t].push(node(u, d)); update(p); } } else { --node_cnt; col[u] = 1; for(int i = vt[u].size() - 1; i >= 0; --i) { int p = vt[u][i].p; update(p); } } } } return 0;}
1 0
- SPOJ QTREE4 Query on a tree IV (边分治 + 堆)
- SPOJ QTREE4 Query on a tree IV(边分治)
- SPOJ-QTREE4 Query on a tree IV(边分治)
- SPOJ 2666 QTREE4 - Query on a tree IV
- spoj qtree4 边分治
- SPOJ Query on a tree
- SPOJ Query on a tree
- SPOJ Query on a tree
- Query on a tree SPOJ
- Query on a tree SPOJ
- SPOJ QTREE4Query on a tree IV
- SPOJ QTREE5Query on a tree V(边分治)
- [SPOJ 375]Query On a Tree(树链剖分)
- SPOJ 375. Query on a tree【树链剖分】
- SPOJ 375. Query on a tree【树链剖分】
- SPOJ QTREE(Query on a tree树链剖分)
- SPOJ 375.Query on a tree
- spoj 375--Query On a Tree [树链剖分]
- N个皇后
- permgen space问题
- CL——Windows下命令行运行C/C++
- uva 127
- linux学习笔记 - 文档权限与目录配置
- SPOJ QTREE4 Query on a tree IV (边分治 + 堆)
- 同步方式比较
- hd1969 Pie
- 20150803 YAHOO军规:如何提高网站速度
- Delphi二维码中文支持、分组、批量打印经验小结
- jQuery选择器总结
- Serv-U FTP Server应用技巧及安全防范
- 将InputStream(输入流)转成String 的方法
- hdu 1166 敌兵布阵