poj 3237 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(树链剖分,线段树)的更多相关文章
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- 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 ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- 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, ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
随机推荐
- (转) IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context ...
- LINUX开机启动过程
LINUX开机启动过程 启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息 ...
- Netty源码阅读(一) ServerBootstrap启动
Netty源码阅读(一) ServerBootstrap启动 转自我的Github Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...
- 常用js函数
1.获得元素到页面的绝对距离 function getPos(obj) { var pos = {left:0, top:0}; while (obj) { pos.left += obj.offse ...
- JavaScript学习总结【12】、JS AJAX应用
1.AJAX 简介 AJAX(音译为:阿贾克斯) = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技 ...
- 青瓷qici - H5小游戏 抽奖机 3 效果设置
现在是万事俱备,只欠东风,好,我们一起动手,先来东风东. 烟花粒子效果 第一个来实现我们的烟花粒子效果,点击我们的粒子,按照下图方式配置. 注意此时我们已经加入了white.png作为粒子特效使用. ...
- data:image/png;base64是什么
大家可能注意到了,网页上有些图片的src或css背景图片的url后面跟了一大串字符,比如: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJ ...
- Ubuntu 13.10 PHP 5.5.x mcrypt missing – Fatal Error: Undefined function mcrypt_encrypt()!
[原文]http://www.tuicool.com/articles/goto?id=myM7veR I had updgraded my Ubuntu from 13.04 to 13.10 la ...
- 005 Python的数值类型
005 Python的数值类型 BIF 指的是内置函数,一般不作为变量命名.如 input,while,if,else,float,等等.整型:整数.(python3.0版本把整型和长整型结合在 ...
- web2.0最全的国外API应用集合
web2.0最全的国外API应用集合 原文地址:http://www.buguat.com/post/98.html 2.0时代,越来越多的API被大家广泛应用,如果你还不了解API是何物,请看这里的 ...