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.

给出一棵边带权的树,初始树上所有节点都是白色。
有两种操作:

C x,改变节点x的颜色,即白变黑,黑变白

A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0)。

树 边分治

试着写了边分治,花式WAWAWA,最后不得已还是开启了标准代码比对。

这么复杂的东西估计过几天就忘,悲伤

果然加上虚点以后内存占用超大啊……边要开到mxn<<4

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF=1e8;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*-''+ch;ch=getchar();}
return x*f;
}
struct edge{
int v,nxt;int w;
}e[mxn<<],eg[mxn<<];
int hd[mxn],mct=;
int tmp[mxn];
void add_edge(int u,int v,int w){//虚点图
e[++mct].v=v;e[mct].nxt=hd[u];e[mct].w=w;hd[u]=mct;return;
}
void add1(int u,int v,int w){//原图
eg[++mct].v=v;eg[mct].nxt=tmp[u];eg[mct].w=w;tmp[u]=mct;return;
}
int n,m;
int c[mxn];//颜色 void Rebuild(int u,int fa){//建立添加了虚点的新图
int ff=;
for(int i=tmp[u];i;i=eg[i].nxt){//tmp存原图边
int v=eg[i].v;
if(v==fa)continue;
if(!ff){
add_edge(u,v,eg[i].w);
add_edge(v,u,eg[i].w);
ff=u;
Rebuild(v,u);
}
else{
c[++n]=;//添加虚点
add_edge(ff,n,);add_edge(n,ff,);
add_edge(n,v,eg[i].w);
add_edge(v,n,eg[i].w);
ff=n;
Rebuild(v,u);
}
}
return;
}
struct node{
int rt,len,ans;
int lc,rc;
priority_queue<pair<int,int> >q;
}t[mxn<<];
bool del[mxn<<];
int pos,mini,mid;
int sz[mxn],tot=;
void DFS_S(int u,int d,int fa){//计算子树各结点距离
add1(u,pos,d);//用原图的空间来存边分治的点边关系
//从当前结点向"管辖它的边代表的结点"连边
if(!c[u]) t[pos].q.push(make_pair(d,u));
sz[u]=;
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa || del[i])continue;
DFS_S(v,d+e[i].w,u);
sz[u]+=sz[v];
}
return;
}
void DFS_mid(int u,int id){
if(max(sz[u],sz[t[pos].rt]-sz[u])<mini){//寻找中心边
mini=max(sz[u],sz[t[pos].rt]-sz[u]);
mid=id;
}
for(int i=hd[u];i;i=e[i].nxt){
if(i!=(id^) && !del[i]){
DFS_mid(e[i].v,i);
}
}
return;
}
void pushup(int p){//处理编号为rt的中心边
t[p].ans=-;
while(!t[p].q.empty() && (c[t[p].q.top().second]==)) t[p].q.pop();
// printf("rt:%d lc:%d rc:%d\n",p,t[p].lc,t[p].rc);
if(!t[p].lc && !t[p].rc){if(!c[t[p].rt])t[p].ans=;}
else{
int tmp=max(t[t[p].lc].ans,t[t[p].rc].ans);
t[p].ans=max(t[p].ans,tmp);
if(!t[t[p].lc].q.empty() && !t[t[p].rc].q.empty())
t[p].ans=max(t[t[p].lc].q.top().first+t[t[p].rc].q.top().first+t[p].len,t[p].ans);
}
return;
}
void update(int u){
c[u]^=;
if(c[u])
for(int i=tmp[u];i;i=eg[i].nxt){
pushup(eg[i].v);
}
else for(int i=tmp[u];i;i=eg[i].nxt){
t[eg[i].v].q.push(make_pair(eg[i].w,u));
pushup(eg[i].v);
}
}
void divide(int u,int p){//边分治
t[p].rt=u;
pos=p;
DFS_S(u,,);
mid=-;mini=INF;
DFS_mid(u,-);
if(mid>){
del[mid]=;del[mid^]=;
int x=e[mid].v,y=e[mid^].v;//先保存两边的点,否则递归过程中mid变了会导致WA
t[p].len=e[mid].w;
t[p].lc=++tot;
t[p].rc=++tot;
divide(x,t[p].lc);
divide(y,t[p].rc);
}
pushup(p);
}
int main(){
int i,j,u,v,w;
n=read();
mct=*n;
for(i=;i<n;i++){
u=read();v=read();w=read();
add1(u,v,w);add1(v,u,w);
}
mct=;
Rebuild(,);
memset(tmp,,sizeof tmp);//初始化原图
mct=;
tot=;
divide(,tot);
char op[];
m=read();
while(m--){
scanf("%s",op);
if(op[]=='A'){
if(t[].ans>=)
printf("%d\n",t[].ans);
else printf("They have disappeared.\n");
}
else{
w=read();
update(w);
}
}
return ;
}

SPOJ QTREE4 - Query on a tree IV的更多相关文章

  1. SPOJ QTREE4 - Query on a tree IV 树分治

    题意: 给出一棵边带权的树,初始树上所有节点都是白色. 有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0). 分析: ...

  2. SPOJ QTREE4 Query on a tree IV ——动态点分治

    [题目分析] 同bzoj1095 然后WA掉了. 发现有负权边,只好把rmq的方式改掉. 然后T了. 需要进行底(ka)层(chang)优(shu)化. 然后还是T 下午又交就A了. [代码] #in ...

  3. SPOJ - QTREE4 Query on a tree IV 边分治

    题目传送门 题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有2个操作,1修改某个点的颜色, 2询问2个白点的之前的路径权值最大和是多少. 题解: 边分治思路. 1.重构图. 因为边分治 ...

  4. 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV

    意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...

  5. SP2666 QTREE4 - Query on a tree IV(LCT)

    题意翻译 你被给定一棵n个点的带边权的树(边权可以为负),点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的权值之和. 一开始所有的点都是白色的. 要求作以下 ...

  6. SPOJ 375. Query on a tree (树链剖分)

    Query on a tree Time Limit: 5000ms Memory Limit: 262144KB   This problem will be judged on SPOJ. Ori ...

  7. SPOJ QTREE Query on a tree 树链剖分+线段树

    题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...

  8. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

  9. spoj 375 Query on a tree(树链剖分,线段树)

      Query on a tree Time Limit: 851MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Sub ...

随机推荐

  1. [vijos]P1514 天才的记忆

    背景 神仙飞啊飞 描述 从前有个人名叫W and N and B,他有着天才般的记忆力,他珍藏了许多许多的宝藏.在他离世之后留给后人一个难题(专门考验记忆力的啊!),如果谁能轻松回答出这个问题,便可以 ...

  2. Docker自学纪实(一)Docker介绍

    先简单了解一下,做个记录,以便不时之需. Docker简介:Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依 ...

  3. Unity基础-Input接口

    input 底层的设备输入接口,在开发中很少用到 Input.GetKey() // Update is called once per frame void Update () { if (Inpu ...

  4. NodeJS基础入门-Event

    大多数Node.js核心API都采用惯用的异步事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器). 例如,net.Server对象会在每次有新连接时触发事件;fs ...

  5. w3resource_MySQL练习: Aggregate_functions

    w3resource_MySQL练习题:Aggregate_functions   1. Write a query to list the number of jobs available in t ...

  6. (转)git常见错误

      error: src refspec master does not match any. 引起该错误的原因是,目录中没有文件,空目录是不能提交上去的 error: insufficient pe ...

  7. Python之多线程与多进程(二)

    多进程 上一章:Python多线程与多进程(一) 由于GIL的存在,Python的多线程并没有实现真正的并行.因此,一些问题使用threading模块并不能解决 不过Python为并行提供了一个替代方 ...

  8. python学习-- 数据库迁移 python manage.py makemigrations 和 python manage.py migrate

    python manage.py makemigrations 和 python manage.py migrate

  9. Farey sequences

    n阶的法里数列是0和1之间最简分数的数列,由小至大排列,每个分数的分母不大于n. Stern-Brocot树(SB Tree)可以生成这个序列 {0/1,1/1} {0/1,1/2,1/1} {0/1 ...

  10. js 抓取页面数据

    数据抓取 主要思路和原理 在根节点document中监听所有需要抓取的事件 在元素事件传递中,捕获阶段获取事件信息,进行埋点 通过getBoundingClientRect() 方法可获取元素的大小和 ...