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. Chapter 4 - How to Fire some Bullets

    Now, we want to let the hero fire some bullets to kill the enemies, add the codes below to set the l ...

  2. 鸟哥的Linux私房菜学习笔记(1)

    2014/10/29 1.档案的权限管理分为三个部分: 拥有者.群组.其他 2.ls -al 命令可以看到档案的详细信息 3.档案的属性中由十个部分构成 第一个部分是档案类型 -代表档案.d代表文件夹 ...

  3. CentOS7安装Puppet+GitLab+Bind

    添加Puppet官方源 rpm -Uvh https://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm 安装Puppet yum -y i ...

  4. Linux删除文件Argument list too long问题的解决方案

    方法一:使用find find . -name 文件 | xargs rm -f 但文件数量过多,find命令也会出现问题: -bash: /bin/find: Argument list too l ...

  5. day-7

    /* 倒数7天了 某一天 某一刻 某次呼吸 我们终将再分离 而我的 自传里 曾经有你 没有遗憾的诗句 诗句里 充满感激 (小仙女博客抄来的233) 是啊 就快要结束了 曲终人散 上午被错误数据卡了一小 ...

  6. jQuery各种选择器总结

    首先介绍几个简单的: id选择器 $('#p1').html('<font color='red'>nihao</font>); 类选择器:表示页面上所有应用了a样式的标签 $ ...

  7. 锱铢必较,从(function(){}())与(function(){})()说起

    今天做JsHint时,碰到一个警告:应该使用(function(){}())而不是(function(){})();看到这个我心想,这两种函数自执行有什么区别吗?自执行用了这么久,感觉对其理解仍然有点 ...

  8. C#中有关字符串去重的解决方案

    今天在群里看到一个同学的面试题 题目中有一个这样的要求 //本地有个文档文件a.txt里面包含的内容分为一段字符串"abacbacde"请编写一个程序,获取文件得到对应的内容,并对 ...

  9. Java GetAndPost

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...

  10. Android - IOExceptionConnection to xxx refused.

    还是stackoverflow上老外牛,往google上type一下,就找到原因了. 今天在使用Apache提供的HttpClient连接Tomcat服务器,使用log捕获异常的时候,提示说:IOEx ...