spoj qtree IV

2666. Query on a tree IV

Problem code: QTREE4

You are given a tree (an acyclic undirected connected graph) with N nodes, and nodes numbered 1,2,3...,N. Each edge has an integer value assigned to it(note that the value can be negative). Each node has a color, white or black. We define dist(a, b) as the sum of the value of the edges on the path from node a to node b.

All the nodes are white initially.

We will ask you to perfrom some instructions of the following form:

  • C a : change the color of node a.(from black to white or from white to black)
  • A : ask for the maximum dist(a, b), both of node a and
    node b must be white(a can be equal to b). Obviously, as long as there
    is a white node, the result will alway be non negative.

Input

  • In the first line there is an integer N (N <= 100000)
  • In the next N-1 lines, the i-th line describes the i-th edge: a
    line with three integers a b c denotes an edge between a, b of value c
    (-1000 <= c <= 1000)
  • In the next line, there is an integer Q denotes the number of instructions (Q <= 100000)
  • In the next Q lines, each line contains an instruction "C a" or "A"

Output

For each "A" operation, write one integer representing its result.
If there is no white node in the tree, you should write "They have disappeared.".

Example

Input:
3
1 2 1
1 3 1
7
A
C 1
A
C 2
A
C 3
A

Output:
2
2
0
They have disappeared.

大意:给出一棵树,每个点非白即黑.求树上最远的两个白点之间的距离,中间必须支持动态修改每个点的黑白状态.

思考:树分治真是个好东西......边分治有一个非常好的性质:就是一条边能将整棵树分成两个部分.(二分)所以合并信息是非常方便的.

我们将每个点到中心边的距离求出来并且保存.对于每条中心边,用一个优先队列来保存对应的最优值.最后我们合并答案即可.

但是边分治的缺点也显而易见.就是菊花树的时候复杂度经常退化.那么怎么做呢? 我们将这棵树重构,就不会那么退化得厉害了.

代码比较慢,凑合着看....

  1 #include<cstdlib>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 #include<cctype>
  7 #include<ctime>
  8 using namespace std;
  9 const int maxn = (int)4e5, inf = 0x3f3f3f3f;
 10 struct E{
 11     int t,w,last;
 12 }e[maxn * 8][3];
 13 int last[maxn * 8][3],edg[3]={1,1,1},ext;
 14 void add1(int x,int y,int w){
 15     e[++edg[ext]][ext] = (E){y,w,last[x][ext]}; last[x][ext] = edg[ext];
 16 }
 17 void add(int x,int y,int w){
 18     add1(x,y,w); add1(y,x,w);
 19 }
 20 int getint(){
 21     int ret = 0,t = 1; char ch = getchar();
 22     while(!isdigit(ch)) t = ch == ‘-‘ ? -1 : t, ch = getchar();
 23     while(isdigit(ch)) ret = ret * 10 + ch - ‘0‘, ch = getchar();
 24     return ret * t;
 25 }
 26 int n,img;
 27 int col[maxn * 4];
 28 void rebuild(int x,int fa){
 29     int las = x;
 30     for(int i = last[x][0]; i; i = e[i][0].last)
 31         if(e[i][0].t != fa){
 32             if(i == last[x][0]) add(x,e[i][0].t,e[i][0].w);
 33             else col[++img] = 1, add(las,img,0), add(img,e[i][0].t,e[i][0].w),las = img;
 34         }
 35     for(int i = last[x][0]; i; i = e[i][0].last)
 36         if(e[i][0].t != fa) rebuild(e[i][0].t, x);
 37 }
 38 struct D{
 39     int x,dis;
 40     bool operator <(const D &b) const{
 41         return dis < b.dis;
 42     }
 43 };
 44 struct SEG{
 45     int ans;
 46     int l,r,mid;
 47     priority_queue<D>q;
 48     void pop(){
 49         while(!q.empty() && col[q.top().x] == 1) q.pop();
 50     }
 51 }T[maxn * 4];
 52 int cnt,mid,node,tmax,p;
 53 int sz[maxn * 4],vis[maxn * 8];
 54 void pushup(int x){
 55     T[x].ans = -1;
 56     T[x].pop();
 57     int l = T[x].l, r = T[x].r;
 58     if(l == 0 && r == 0){
 59         if(!T[x].q.empty()) T[x].ans = 0;
 60     }else{
 61         if(T[x].ans < T[l].ans) T[x].ans = T[l].ans;
 62         if(T[x].ans < T[r].ans) T[x].ans = T[r].ans;
 63         if(!T[l].q.empty() && !T[r].q.empty())
 64             T[x].ans = max(T[x].ans, T[l].q.top().dis + T[r].q.top().dis + T[x].mid);
 65     }
 66 }
 67 void getsize(int x,int fa,int dis){
 68     sz[x] = 1;
 69     add1(x,p,dis);
 70     if(col[x] == 0) T[p].q.push((D){x,dis});
 71     for(int i = last[x][1]; i; i = e[i][1].last)
 72         if(e[i][1].t != fa && !vis[i]){
 73             getsize(e[i][1].t, x, dis + e[i][1].w);
 74             sz[x] += sz[e[i][1].t];
 75         }
 76 }
 77 void getmid(int x,int id){
 78     int Max = max(sz[x], node - sz[x]);
 79     if(tmax > Max) tmax = Max, mid = id;
 80     for(int i = last[x][1]; i; i = e[i][1].last)
 81         if(!vis[i] && i != id && i != (id^1)) getmid(e[i][1].t, i);
 82 }
 83 void work(int tp,int x){
 84     p = tp;
 85     getsize(x,0,0);
 86     tmax = inf; node = sz[x]; getmid(x,mid = 0);
 87     vis[mid] = vis[mid^1] = 1;
 88     if(mid){
 89         int l = e[mid][1].t, r = e[mid^1][1].t;
 90         T[tp].mid = e[mid][1].w;
 91         work(T[tp].l = ++cnt, l);
 92         work(T[tp].r = ++cnt, r);
 93     }
 94     pushup(tp);
 95 }
 96 void solve(){
 97     int Q = getint(),x;
 98     char ch;
 99     while(Q--){
100         scanf("%c\n",&ch);
101         if(ch == ‘A‘){
102             if(T[1].ans >= 0) printf("%d\n",T[1].ans);
103             else printf("They have disappeared.\n");
104         }
105         else{
106             x = getint();
107             col[x] ^= 1;
108             for(int i = last[x][2]; i; i = e[i][2].last){
109                 if(col[x] == 0)T[e[i][2].t].q.push((D){x,e[i][2].w});
110                 pushup(e[i][2].t);
111             }
112         }
113     }
114 }
115 int main()
116 {
117     freopen("qtree.in","r",stdin);
118     freopen("qtree.out","w",stdout);
119     img = n = getint();
120     for(int i = 1; i < n; ++i){
121         int u = getint(), v = getint(), w = getint();
122         add(u,v,w);
123     }
124     ext = 1; rebuild(1,0);
125     ext = 2; work(cnt = 1, 1);
126     solve();
127     return 0;
128 }

时间: 2024-10-14 12:25:31

spoj qtree IV的相关文章

SPOJ QTREE系列 树上分治问题。

375.Query on a tree  [QTREE] 有两个操作: (1)修改第i条边的边权 (2)询问a到b路径上的边权最大值. 树链剖分入门题.树链剖分+线段树维护最大值.修改/查询均为O(log^2). 很懒,没有写. 913.Query on a tree II [QTREE2] 有两个操作: (1)询问a到b的距离. (2)询问a到b路径上的第k个点. 很容易想到倍增LCA. 路径上的第k个点,要么是a的第k个父亲,要么是b的第k'个父亲,同样可以倍增实现. 询问都是O(logn)

SPOJ - QTREE 375 Query on a tree 树链剖分+线段树

操作1:修改第k条边权. 操作2:询问两点间最大边权. 树链剖分,然后线段树维护最大值 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #inclu

SPOJ QTREE 系列解题报告

题目一 : SPOJ 375 Query On a Tree http://www.spoj.com/problems/QTREE/ 给一个树,求a,b路径上最大边权,或者修改a,b边权为t. 1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 7 using namespace s

SPOJ QTREE 375. Query on a tree

SPOJ Problem Set (classical) 375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHA

SPOJ QTREE Query on a tree ——树链剖分 线段树

[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 20005 int T,n,fr[maxn],h[maxn],to[maxn],ne[maxn]

SPOJ QTREE 树链剖分

375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of

【学术篇】SPOJ QTREE 树链剖分

发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能得28pts.. 重新见到这些失踪的dalao灰常开心, 于是想让自己心情稍微差一点, 就想着把自己昨天写WA的QTREE重构一遍吧.. 于是重构的sb链剖果然挂掉了... 出现了各种各样的漏洞... 忘记各种各样的句子, 然而退化成了暴力小数据也随便过看不出来啊~~~ 但是还是在1h之内调对了_(

SPOJ QTREE

QTREE /* 题目大意:维护一棵树,允许修改边权以及查询链上最大值 题解:我们将边权转为点权,标记在深度较深的点上,树链剖分后用线段树处理即可 */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=20010; int top[N],nxt[N],v[N],g[N],d[N],son[N],f[N],size[N],st[N],en[

【SPOJ QTREE】树链剖分模板

用线段树求解,这里注意由于求的是路径最大值,注意一下细节. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 10010; #define lson (pos<<1) #define rson (pos<<1|1) const int INF = (1 << 30); int n; //-------