【POJ3237】Tree(树链剖分+线段树)
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:
CHANGEivChange the weight of the ith edge to v NEGATEabNegate the weight of every edge on the path from a to b QUERYabFind 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
DONESample 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(树链剖分+线段树)的更多相关文章
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- 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 ...
- 【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 ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
随机推荐
- LabVIEW系列——拍振现象重现
- MVVM架构的一次实践,重写iOS头条客户端
前言: 一个iOS头条APP,使用MVVM架构实现,代码中有注释,封装了AFN网络请求,解媾代码,使用起来非常方便.用最经典的TableView展示,后续不断更新,喜欢就star或fork一下,有问题 ...
- 使用C#WebClient类访问(上传/下载/删除/列出文件目录)由IIS搭建的http文件服务器
前言 为什么要写这边博文呢?其实,就是使用C#WebClient类访问由IIS搭建的http文件服务器的问题花了我足足两天的时间,因此,有必要写下自己所学到的,同时,也能让广大的博友学习学习一下. 本 ...
- 也许是关于C#的一些常见误区
写这点东西主要是看到知乎上有人在讨论相关的问题,但是有不少人都在说一些不严谨,甚至是完全错误 但是流传甚广的东西,甚至是一些大神都在说,以下根据我的回答总结. 一个很常见又很低级的误区是:认为引 ...
- android UI生成器
可根据选择的效果生成资源 http://jgilfelt.github.io/android-actionbarstylegenerator/#name=example&compat=sher ...
- SQL排序 空值的后面
按sort排序,sort为空的在后面 end),sort
- 菱形实现气泡Bubble,菱形画箭头,菱形画三角形
菱形实现气泡Bubble,菱形画箭头,菱形画三角形 >>>>>>>>>>>>>>>>>>&g ...
- javascript实现继承的6种方式
/*1.原型链继承*/ function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = funct ...
- Java-struts2 通过MODEL接收表单数据的方法
接收数据的时候经常会出问题: 1.记住action = “”到的路径,最好用全路径 <a href="../Struts/user/hello?user.name=xxzzzzzzzz ...
- (转)Apache2 httpd.conf 配置详解 (二)
转之--http://jafy00.blog.51cto.com/2594646/508205 DocumentRoot "/usr/local/apache-2.2.6/htdocs&qu ...