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. skynet 学习笔记-netpack模块(1)

    int luaopen_netpack(lua_State *L) { luaL_checkversion(L); luaL_Reg l[] = { { "pop", lpop } ...

  2. 从输入URL到页面加载完成的过程中都发生了什么事情?

    为了便于理解,我将整个过程分为了六个问题来展开. 第一个问题:从输入 URL 到浏览器接收的过程中发生了什么事情? 从触屏到 CPU 首先是「输入 URL」,大部分人的第一反应会是键盘,不过为了与时俱 ...

  3. linux系统下的用户文件句柄数限制

    linux系统下的用户文件句柄数限制 文章来源:企鹅号 为什么要修改用户打开的文件数 系统默认单个进程可以打开1024个文件,对于一些应用如tomcat.oracle等,运行时经常open成千上万个文 ...

  4. numpy的linspace使用详解

    文档地址: https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html Parameters(参数): start ...

  5. matplotlib绘图(四)

    控制文字属性的方法: 所有的方法都会返回一个matplotlib.text.Text对象  文本注释: annnotate() xy参数设置箭头指示的位置,xytext参数设置注释文字的位置 arro ...

  6. pandas删除及其映射修改操作。

    1.使用drop_duplicates()函数删除重复的行 df.drop_duplicates() 2.映射 映射的含义,创建一个映射关系,把values元素和一个特定的标签或字符串绑定 map = ...

  7. [提供可行性脚本] RHEL 7/CentOS 7/Fedora28 重命名网卡名称

    实验说明: 在许多自动化任务中,脚本往往是通过读取配置文件来获取信息的,红帽系的系统自升级之后(CentOS7/RHEL7),网卡命名采用“一致性网络设备接口”的命名方法,导致不同设备的不同网卡名称各 ...

  8. 腾讯云Ubuntu服务器修改root密码

    1.修改root密码 执行以下命令,按照提示修改密码 sudo passwd root 2.修改ssh配置 执行以下命令 sudo vi /etc/ssh/sshd_config 找到 PermitR ...

  9. python中文件操作的六种模式及对文件某一行进行修改的方法

    一.python中文件操作的六种模式分为:r,w,a,r+,w+,a+ r叫做只读模式,只可以读取,不可以写入 w叫做写入模式,只可以写入,不可以读取 a叫做追加写入模式,只可以在末尾追加内容,不可以 ...

  10. python之序列化

    什么叫序列化? 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes. 把字符转换成内存数据类型,叫反序列化. 为什么要序列化? 你 ...