Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 throughN − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGEiv Change the weight of the ith edge to v
NEGATEab Negate the weight of every edge on the path from a to b
QUERYab Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers ab and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3
 

【题意】

指定一颗树上有3个操作:

  询问操作,询问a点和b点之间的路径上最长的那条边的长度;

  取反操作,将a点和b点之间的路径权值都取相反数;

  变化操作,把某条边的权值x变成指定的值。

【分析】

  人生第一道树剖题,调了好久啊,200+的代码还打了对拍= =

  就是裸的树链剖分+线段树啦。

  就是线段树打得不够熟练所以调了那么久,lazy标记不大会用~~

  

  树剖的主要过程就是两次的dfs,第一次求fa,第二次求top。询问过程就是一直跳,跳到两个东西在一条重链上去。

  因为某种特殊性质,所以他很快。。

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 10010
#define INF 100000000 int fa[Maxn],first[Maxn],size[Maxn],dep[Maxn],son[Maxn];
int w[Maxn],top[Maxn];int wl;
int b[Maxn][]; struct node
{
int x,y,c,next;
}t[*Maxn];int len; struct nnode
{
int l,r,lc,rc,mx,mn;
bool lazy;
}tr[*Maxn];int tl; int mymax(int x,int y) {return x>y?x:y;}
int mymin(int x,int y) {return x<y?x:y;} void ins(int x,int y,int c)
{
t[++len].x=x;t[len].y=y;t[len].c=c;
t[len].next=first[x];first[x]=len;
} void dfs1(int x,int f)
{
fa[x]=f;dep[x]=dep[f]+;size[x]=;
son[x]=;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
{
dfs1(t[i].y,x);
size[x]+=size[t[i].y];
if(size[t[i].y]>size[son[x]]) son[x]=t[i].y;
}
} void dfs2(int x,int tp)
{
w[x]=++wl;
top[x]=tp;
if(size[x]!=) dfs2(son[x],tp);
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
{
dfs2(t[i].y,t[i].y);
}
} int build(int l,int r)
{
int x=++tl;
tr[x].l=l;tr[x].r=r;tr[x].mx=-INF;tr[x].mn=INF;tr[x].lazy=;
if(l!=r)
{
int mid=(l+r)>>;
tr[x].lc=build(l,mid);
tr[x].rc=build(mid+,r);
}
return x;
} void upd(int x)
{
if(!tr[x].lazy) return;
tr[x].lazy=;
int a=tr[x].mx;
tr[x].mx=-tr[x].mn;tr[x].mn=-a;
if(tr[x].l==tr[x].r) return;
tr[tr[x].lc].lazy=!tr[tr[x].lc].lazy;
tr[tr[x].rc].lazy=!tr[tr[x].rc].lazy;
} void change(int x,int y,int c)
{
upd(x);
if(tr[x].l==tr[x].r)
{
tr[x].mx=c;
tr[x].mn=c;
return;
}
int mid=(tr[x].l+tr[x].r)>>;
if(y<=mid) change(tr[x].lc,y,c);
else change(tr[x].rc,y,c);
upd(tr[x].lc);upd(tr[x].rc);
tr[x].mx=mymax(tr[tr[x].lc].mx,tr[tr[x].rc].mx);
tr[x].mn=mymin(tr[tr[x].lc].mn,tr[tr[x].rc].mn);
} int qtree(int x,int l,int r)
{
upd(x);
if(tr[x].l==l&&tr[x].r==r) return tr[x].mx;
int mid=(tr[x].l+tr[x].r)>>;
if(r<=mid) return qtree(tr[x].lc,l,r);
if(l>mid) return qtree(tr[x].rc,l,r);
return mymax(qtree(tr[x].lc,l,mid),qtree(tr[x].rc,mid+,r));
} int query(int x,int y)
{
int tmp=-INF;
int f1=top[x],f2=top[y];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(x,y);
}
tmp=mymax(qtree(,w[f1],w[x]),tmp);
x=fa[f1];
f1=top[x];
}
if(x==y) return tmp;
if(dep[x]<dep[y]) swap(x,y);
return mymax(tmp,qtree(,w[son[y]],w[x]));
} void change2(int x,int l,int r)
{
upd(x);
if(tr[x].l==l&&tr[x].r==r)
{
tr[x].lazy=!tr[x].lazy;
upd(x);
return;
}
int mid=(tr[x].l+tr[x].r)>>;
if(r<=mid) change2(tr[x].lc,l,r);
else if(l>mid) change2(tr[x].rc,l,r);
else
{
change2(tr[x].lc,l,mid);
change2(tr[x].rc,mid+,r);
}
upd(tr[x].lc);upd(tr[x].rc);
tr[x].mx=mymax(tr[tr[x].lc].mx,tr[tr[x].rc].mx);
tr[x].mn=mymin(tr[tr[x].lc].mn,tr[tr[x].rc].mn);
} void negate1(int x,int y)
{
int f1=top[x],f2=top[y];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(x,y);
}
change2(,w[f1],w[x]);
x=fa[f1];
f1=top[x];
}
if(x==y) return;
if(dep[x]<dep[y]) swap(x,y);
change2(,w[son[y]],w[x]);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
memset(first,,sizeof(first));
len=;
for(int i=;i<n;i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
b[i][]=x;b[i][]=y;b[i][]=c;
ins(x,y,c);ins(y,x,c);
}
dep[]=;size[]=;
dfs1(,);wl=;
dfs2(,);
char s[];
tl=;
build(,wl);
for(int i=;i<n;i++)
{
if(dep[b[i][]]<dep[b[i][]]) swap(b[i][],b[i][]);
change(,w[b[i][]],b[i][]);
}
while()
{
scanf("%s",s);
if(s[]=='D') break;
if(s[]=='Q')
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y));
}
else if(s[]=='C')
{
int x,y;
scanf("%d%d",&x,&y);
change(,w[b[x][]],y);//单点修改
}
else
{
int x,y;
scanf("%d%d",&x,&y);
negate1(x,y);
}
}
}
return ;
}

[POJ3237]

2016-05-08 14:50:31

【POJ3237】Tree(树链剖分+线段树)的更多相关文章

  1. POJ3237 Tree 树链剖分 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...

  2. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  3. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  4. 【CF725G】Messages on a Tree 树链剖分+线段树

    [CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...

  5. Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  6. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  7. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  8. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  9. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

随机推荐

  1. HDU2019JAVA

    数列有序! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...

  2. 也谈android开发图像压缩

    long long ago,给学院做的一个通讯录App需要有一个上传图像的功能,冥思苦想,绞尽脑汁后来还是没解决(学生时代的事),于是就直接上传原图了,一张图片2M到3M,这样我的应用发布之后,那绝对 ...

  3. WebService学习笔记系列(一)

    webservice主要是解决两个系统或者两个应用程序之间的远程调用,它提供了一种通过web方式访问的api,调用是跨语言.跨平台的. webservice的客户端与服务端进行交互的时候使用xml来传 ...

  4. Spring AOP体系学习总结:

    二.Spring AOP体系学习总结: 要理解AOP整体的逻辑需要理解一下Advice,Pointcut,Advisor的概念以及他们的关系. Advice是为Spring Bean提供增强逻辑的接口 ...

  5. UDP—Socket,套接字聊天简单的聊天程序。

    思路:(发送端) 1.既然需要聊天.就应该怎么建立聊天程序,,DatagramSocket对象http://www.w3cschool.cc/manual/jdk1.6/ DatagramSocket ...

  6. c语言学习之基础知识点介绍(四):算术运算符和逗号表达式

    本节主要介绍c语言中运算符. 运算符主要分为四类: 1.算术运算符 加(+),减(-),乘(*),除(/),取余(%,两数相除,得到余数) 2.关系运算符 3.逻辑运算符 4.换位运算符 下面将依次介 ...

  7. WIN7 VMware Ubuntu虚拟机连接secureCRT及ftp传输文件

    一.安装vmware没有问题,网络设置以NAT方式(VMnet8是vmware专属的虚拟网卡).安装完毕后设置虚拟机的 VirtualNetworkEditor(可以再开始->所有程序VMwar ...

  8. 枚举N行N列的自然数列

    数据库环境:SQL SERVER 2005 现有一个需求,要枚举1-50个自然数,分10行5列展示.如图,

  9. HTTP状态吗汇录

    页面Http状态查询工具说明 建议直接Ctrl+F来查找状态码 如果向您的服务器发出了某项请求要求显示您网站上的某个网页,那么,您的服务器会返回 HTTP 状态代码以响应该请求. 如果向您的服务器发出 ...

  10. WPF常用控件应用demo

    WPF常用控件应用demo 一.Demo 1.Demo截图如下: 2.demo实现过程 总体布局:因放大缩小窗体,控件很根据空间是否足够改变布局,故用WrapPanel布局. <ScrollVi ...