Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 7268   Accepted: 1969

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 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:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b 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 a, b 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

Source

【思路】

树链剖分,线段树。

又练了一边线段树<_<,bug满天飞T^T,线段树还得再做点题。

线段树:维护mx mn分别代表线段最大最小值,对于NEGATE操作打一个f标记,作用时直接将mx mn取负后交换即可。注意一下pushdown和maintain。

【代码】

 #include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int N = +;
const int INF = 1e9; struct Node { int l,r,mx,mn,f;
}T[N<<];
struct Edge {
int u,v,w;
Edge(int u=,int v=,int w=) :u(u),v(v),w(w) {};
};
int n,q,z,d[N][];
vector<Edge> es;
vector<int> g[N]; void adde(int u,int v,int w) {
es.push_back(Edge(u,v,w));
int m=es.size();
g[u].push_back(m-);
}
//INIT
int top[N],son[N],dep[N],fa[N],siz[N],w[N];
void dfs1(int u) {
son[u]=; siz[u]=;
for(int i=;i<g[u].size();i++) {
int v=es[g[u][i]].v; //
if(v!=fa[u]) {
fa[v]=u , dep[v]=dep[u]+;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int tp) {
top[u]=tp; w[u]=++z;
if(son[u]) dfs2(son[u],tp);
for(int i=;i<g[u].size();i++) {
int v=es[g[u][i]].v;
if(v!=fa[u] && v!=son[u]) dfs2(v,v);
}
}
//SEGMENT TREE
//标记 该结点已被作用而子结点仍未作用
//pushdown 作用于访问节点 即只要访问就pushdown
void pushdown(int u) { //下传标记 同时作用于子结点
if(T[u].f && T[u].l<T[u].r) {
int lc=u<<,rc=lc|;
T[u].f=;
T[lc].f^= ,T[rc].f^=;
int t;
t=T[lc].mn,T[lc].mn=-T[lc].mx,T[lc].mx=-t;
t=T[rc].mn,T[rc].mn=-T[rc].mx,T[rc].mx=-t;
}
}
void maintain(int u) {
T[u].mx=max(T[u<<].mx,T[u<<|].mx);
T[u].mn=min(T[u<<].mn,T[u<<|].mn);
}
void build(int u,int L,int R) {
T[u].l=L,T[u].r=R;
T[u].mn=INF , T[u].mx=-INF , T[u].f=;
if(L==R) return ; //
int M=(L+R)>>;
build(u<<,L,M) , build(u<<|,M+,R);
}
void change(int u,int r,int x) {
pushdown(u); //
if(T[u].l==T[u].r) T[u].mn=T[u].mx=x;
else {
int M=(T[u].l+T[u].r)>>; //
if(r<=M) change(u<<,r,x);
else change(u<<|,r,x);
maintain(u);
}
}
void Negate(int u,int L,int R) {
pushdown(u);
if(L<=T[u].l && T[u].r<=R) {//打标记 同时作用于当前结点
T[u].f=;
int t; t=T[u].mn,T[u].mn=-T[u].mx,T[u].mx=-t; //
}
else {
int M=(T[u].l+T[u].r)>>;
if(L<=M) Negate(u<<,L,R);
if(M<R) Negate(u<<|,L,R);
maintain(u);
}
}
int query(int u,int L,int R) {
pushdown(u);
if(L<=T[u].l && T[u].r<=R) return T[u].mx;
else {
int M=(T[u].l+T[u].r)>>;
int ans=-INF;
if(L<=M) ans=max(ans,query(u<<,L,R));
if(M<R) ans=max(ans,query(u<<|,L,R));
return ans;
}
} //树链剖分
void modify(int u,int v) {
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
Negate(,w[top[u]],w[u]);
u=fa[top[u]];
}
if(u==v) return ;
if(dep[u]>dep[v]) swap(u,v);
Negate(,w[son[u]],w[v]); //
}
int query(int u,int v) {
int mx=-INF;
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
mx=max(mx,query(,w[top[u]],w[u]));
u=fa[top[u]];
}
if(u==v) return mx;
if(dep[u]>dep[v]) swap(u,v);
mx=max(mx,query(,w[son[u]],w[v]));
return mx;
} void read(int& x) {
char c=getchar();
while(!isdigit(c)) c=getchar();
x=;
while(isdigit(c))
x=x*+c-'' , c=getchar();
}
int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
int T; read(T);
while(T--) {
read(n);
z=; es.clear();
FOR(i,,n) g[i].clear();
int u,v,c;
FOR(i,,n-) {
read(u),read(v),read(c);
d[i][]=u,d[i][]=v,d[i][]=c;
adde(u,v,c),adde(v,u,c);
}
dfs1(),dfs2(,);
build(,,z);
FOR(i,,n-) {
if(dep[d[i][]]<dep[d[i][]]) swap(d[i][],d[i][]);
change(,w[d[i][]],d[i][]);
}
char s[];
while(scanf("%s",s)== && s[]!='D') {
read(u),read(v);
if(s[]=='C') change(,w[d[u][]],v);
else if(s[]=='N') modify(u,v);
else printf("%d\n",query(u,v));
}
}
return ;
}

poj 3237 Tree(树链剖分,线段树)的更多相关文章

  1. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  2. 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 ...

  3. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  4. POJ3237 Tree 树链剖分 线段树

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

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

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

  6. 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, ...

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

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

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

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

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

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

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

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

随机推荐

  1. RM-Linux驱动--Watch Dog Timer(看门狗)驱动分析

    from:http://blog.csdn.net/geekcome/article/details/6595265 硬件平台:FL2440 内核版本:2.6.28 主机平台:Ubuntu 11,04 ...

  2. easy ui tree 取复选框打勾的值

    var nodes = $('#basetree').tree('getChecked'); var cnode = ''; for ( var i = 0; i < nodes.length; ...

  3. ubuntu 下安装 apache php mysql

    ubuntu 安装 apache+php+mysql1.打开终端,输入“sudo apt-get install apache2”,回车;(安装apache2.0或2.x新版本,系统会自动查找新的版本 ...

  4. demo_07选择器练习

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  5. php中引用符号(&amp;)的使用详解

    php的引用就是在变量或者函数.对象等前面加上&符号,在PHP 中引用的意思是:不同的名字访问同一个变量内容,下面介绍如何使用PHP的引用 与C语言中的指针是有差别的.C语言中的指针里面存储的 ...

  6. python—cookielib模块对cookies的操作

    最近用python写爬虫爬了点数据,确实是很好用的东西,今天对python如何操作cookie进行一下总结. python内置有cookielib模块操作cookie,配合urllib模块就可以了很轻 ...

  7. sql server 表空间

    在SqlServer2005中,建表时是默认把所有的表都保存在PRIMARY默认表空间中的.当数据库中表很多,并且数据量很大时,会导致数据库性能严重下降,有必要将一些大的表放到不同的表空间中去.主要的 ...

  8. 查看sqlserver数据库的端口号

    最近正在用sqlserver作为java的数据库进行开发,在写连接字符串的时候,想起一个问题,怎么查找sqlserver的端口号呢?有两种方法 1,用存储过程 --查询端口号exec sys.sp_r ...

  9. 定位 -CLGeocoder - 编码

    #import "ViewController.h" #import <CoreLocation/CoreLocation.h> @interface ViewCont ...

  10. Android中JNI编程的那些事儿(1)

    转:Android中JNI编程的那些事儿(1)http://mobile.51cto.com/android-267538.htm Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须 ...