SPOJ QTREE4 - Query on a tree IV
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的更多相关文章
- SPOJ QTREE4 - Query on a tree IV 树分治
题意: 给出一棵边带权的树,初始树上所有节点都是白色. 有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0). 分析: ...
- SPOJ QTREE4 Query on a tree IV ——动态点分治
[题目分析] 同bzoj1095 然后WA掉了. 发现有负权边,只好把rmq的方式改掉. 然后T了. 需要进行底(ka)层(chang)优(shu)化. 然后还是T 下午又交就A了. [代码] #in ...
- SPOJ - QTREE4 Query on a tree IV 边分治
题目传送门 题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有2个操作,1修改某个点的颜色, 2询问2个白点的之前的路径权值最大和是多少. 题解: 边分治思路. 1.重构图. 因为边分治 ...
- 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV
意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...
- SP2666 QTREE4 - Query on a tree IV(LCT)
题意翻译 你被给定一棵n个点的带边权的树(边权可以为负),点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的权值之和. 一开始所有的点都是白色的. 要求作以下 ...
- SPOJ 375. Query on a tree (树链剖分)
Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Ori ...
- 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 ...
- QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树
Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...
- spoj 375 Query on a tree(树链剖分,线段树)
Query on a tree Time Limit: 851MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Sub ...
随机推荐
- Spring中使用事务搭建转账环境 转账操作,
演示不使用事务出现异常情况 Dao层两个方法lessMoney()和moreMoney() package com.swift; import org.springframework.jdbc.cor ...
- ios sinaweibo 客户端(三)
这个页面要讲述的是用户的粉丝列表,下面是效果图: 可以看到这个视图明显也是一个tableview,在每一个cell中包含的有三个部分的内容:粉丝头像image,粉丝昵称label,我和粉丝之间的相互关 ...
- error PRJ0019: 工具从 “正在执行生成后事件... ”
error PRJ0019: 工具从"正在执行生成后事件..." 原因是属性->生成事件->生成后事件 命令行设置错误导致的,修改即可 因为path前面有空格,所以这里 ...
- 【线段树 树链剖分 差分 经典技巧】loj#3046. 「ZJOI2019」语言【未完】
还是来致敬一下那过往吧 题目分析 先丢代码 #include<bits/stdc++.h> ; ; ; struct node { int top,son,fa,tot; }a[maxn] ...
- ubuntu系统普通用户密码忘记之重置
当我们在使用ubuntu系统忘记普通用户登录密码的时候,会被系统在登录界面拒之门外而不得入,这时候只好需要我们去重新设置密码,具体做法如下: 系统重启,在GRUB模式下选择Advanced Optio ...
- How To Add Swap Space on Ubuntu 16.04
Introduction One of the easiest way of increasing the responsiveness of your server and guarding aga ...
- 在 Ubuntu 环境下实现插入鼠标自动关闭触摸板
Ubuntu 以及其他衍生版本,如 Linux Mint 等等都可以用官方的 PPA 来安装"触摸板指示"应用程序.打开一个终端,运行以下命令: sudo add-apt-repo ...
- destoon 支付异步接口文件 notify.php 调试方式
在if($verify_result) { 之前复制这三个变量 就可以直接访问notify.php 启用调试模式 或者 逐步echo 相关变量来调试 错误原因 notify.php没有入口文件 是 ...
- 14-15.Yii2.0模型的创建/读取数据使用,框架防止sql注入
目录 创建数据库 表article 配置 db.php 连接数据库 创建控制器 HomeController.php 创建models 创建数据库 表article 1.创建库表 CREATE TAB ...
- 在linux下安装并运行scrapyd
系统:centos7.4 安装scrapyd:pip isntall scrapyd 因为我腾讯云上是python2与python3并存的 所以我执行的命令是:pip3 isntall scrapyd ...