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 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 好惨啊……有一个加1的没写结果最裸的树链剖分调了一整天
线段树维护最大值和最小值,对于一条链上权值取反的操作只要mx=-mn,mn=-mx即可
#include<cstdio>
#include<iostream>
#include<cstring>
#define LL long long
#define inf 1000000000
#define N 10010
using namespace std;
int bin[15]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384};
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct segtree{int l,r,mx,mn,tag;}tree[4*N];
struct edge{int to,next,v;}e[2*N];
int T,n,cnt,tt,mx;
char ch[10];
int head[N];
int fa[N][15],son[N],depth[N],v[N];
bool mrk[N];
int place[N],pplace[N],belong[N];
int query[N];
inline void revswap(int &a,int &b){int t=a;a=-b;b=-t;}
inline void ins(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].v=w;
e[cnt].next=head[u];
head[u]=cnt;
}
inline void insert(int u,int v,int w)
{
ins(u,v,w);
ins(v,u,w);
}
inline void dfs(int x,int dep)
{
if (mrk[x])return;mrk[x]=1;
depth[x]=dep;son[x]=1;
for (int i=1;i<15;i++)
if (bin[i]<=depth[x])
fa[x][i]=fa[fa[x][i-1]][i-1];
else break;
for (int i=head[x];i;i=e[i].next)
if (!mrk[e[i].to])
{
fa[e[i].to][0]=x;
dfs(e[i].to,dep+1);
v[e[i].to]=e[i].v;
son[x]+=son[e[i].to];
query[(i+1)>>1]=e[i].to;
}
}
inline void dfs2(int x,int chain)
{
place[x]=++tt;pplace[tt]=x;
belong[x]=chain;
int res=0,mx=-inf;
for (int i=head[x];i;i=e[i].next)
if (fa[x][0]!=e[i].to)
{
if (son[e[i].to]>mx)
{
mx=son[e[i].to];
res=e[i].to;
}
}
if (!res)return;
dfs2(res,chain);
for (int i=head[x];i;i=e[i].next)
if (fa[x][0]!=e[i].to&&res!=e[i].to)
dfs2(e[i].to,e[i].to);
}
inline int LCA(int a,int b)
{
if (depth[a]<depth[b])swap(a,b);
int res=depth[a]-depth[b];
for (int i=0;i<15;i++)
if (res & bin[i]) a=fa[a][i];
for (int i=14;i>=0;i--)
if (fa[a][i]!=fa[b][i])
{
a=fa[a][i];
b=fa[b][i];
}
if (a==b)return a;
return fa[a][0];
}
inline void pushdown(int k)
{
tree[k].tag=0;
tree[k<<1].tag^=1;tree[k<<1|1].tag^=1;
revswap(tree[k<<1].mx,tree[k<<1].mn);
revswap(tree[k<<1|1].mx,tree[k<<1|1].mn);
}
inline void update(int k)
{
tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
tree[k].mn=min(tree[k<<1].mn,tree[k<<1|1].mn);
}
inline void buildtree(int now,int l,int r)
{
tree[now].l=l;tree[now].r=r;
if (l==r)
{
tree[now].mx=tree[now].mn=v[pplace[l]];
return;
}
int mid=(l+r)>>1;
buildtree(now<<1,l,mid);
buildtree(now<<1|1,mid+1,r);
update(now);
}
inline void change_in_tree(int now,int x,int y)
{
int l=tree[now].l,r=tree[now].r;
if (l!=r&&tree[now].tag)pushdown(now);
if (l==r)
{
tree[now].mx=tree[now].mn=y;
return;
}
int mid=(l+r)>>1;
if (x<=mid)change_in_tree(now<<1,x,y);
else change_in_tree(now<<1|1,x,y);
update(now);
}
inline void negate_in_tree(int now,int x,int y)
{
int l=tree[now].l,r=tree[now].r;
if (l!=r&&tree[now].tag)pushdown(now);
if (l==x&&r==y)
{
revswap(tree[now].mx,tree[now].mn);
tree[now].tag=1;
return;
}
int mid=(l+r)>>1;
if (y<=mid)negate_in_tree(now<<1,x,y);
else if (x>mid)negate_in_tree(now<<1|1,x,y);
else
{
negate_in_tree(now<<1,x,mid);
negate_in_tree(now<<1|1,mid+1,y);
}
update(now);
}
inline void ask_in_tree(int now,int x,int y)
{
int l=tree[now].l,r=tree[now].r;
if (l!=r&&tree[now].tag)pushdown(now);
if (l==x&&r==y)
{
mx=max(mx,tree[now].mx);
return;
}
int mid=(l+r)>>1;
if (y<=mid)ask_in_tree(now<<1,x,y);
else if (x>mid)ask_in_tree(now<<1|1,x,y);
else
{
ask_in_tree(now<<1,x,mid);
ask_in_tree(now<<1|1,mid+1,y);
}
}
inline void reverse(int from,int to)
{
if (from==to)return;
int l,r;
while (belong[from]!=belong[to])
{
l=place[belong[from]];r=place[from];
negate_in_tree(1,l,r);
from=fa[belong[from]][0];
}
if (place[to]+1<=place[from])
negate_in_tree(1,place[to]+1,place[from]);
}
inline int ask(int from,int to)
{
int l,r;mx=-inf;
if (from==to)return mx;
while (belong[from]!=belong[to])
{
l=place[belong[from]];r=place[from];
ask_in_tree(1,l,r);
from=fa[belong[from]][0];
}
if (place[to]+1<=place[from])
ask_in_tree(1,place[to]+1,place[from]);
return mx;
}
inline void work()
{
memset(tree,0,sizeof(tree));
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
memset(mrk,0,sizeof(mrk));
memset(query,0,sizeof(query));
memset(place,0,sizeof(place));
memset(pplace,0,sizeof(pplace));
memset(belong,0,sizeof(belong));
memset(fa,0,sizeof(fa));
memset(son,0,sizeof(son));
memset(depth,0,sizeof(depth));
memset(v,0,sizeof(v));
tt=cnt=0;
n=read();
for (int i=1;i<n;i++)
{
int x=read(),y=read(),z=read();
insert(x,y,z);
}
dfs(1,0);
dfs2(1,1);
buildtree(1,1,n);
while (scanf("%s",ch+1)&&ch[1]!='D')
{
int a=read(),b=read();
if (ch[1]=='C')change_in_tree(1,place[query[a]],b);
if (ch[1]=='N')
{
int c=LCA(a,b);
reverse(a,c);
reverse(b,c);
}
if (ch[1]=='Q')
{
int c=LCA(a,b);
printf("%d\n",max( ask(a,c),ask(b,c) ));
}
}
}
int main()
{
T=read();
while (T--)work();
}
poj3237 Tree的更多相关文章
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- [POJ3237]Tree解题报告|树链剖分|边剖
关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...
- POJ3237 Tree(树剖+线段树+lazy标记)
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbe ...
- POJ3237 Tree (树链剖分)
通过打懒标记实现区间取反,和线段树基本操作都差不多. 本题还是一道边权化为点权的问题. 200行巨长代码: 1 #include<cstdio> 2 #include<cstring ...
- 【poj3237】 Tree
http://poj.org/problem?id=3237 (题目链接) 树链剖分模板题,然而这150+行的程序我调了一天,历经艰辛,终于ac.. 题意 给出一个n个节点的带权树,要求维护操作:1. ...
- 【POJ3237】Tree 树链剖分+线段树
[POJ3237]Tree Description You are given a tree with N nodes. The tree's nodes are numbered 1 through ...
- 【POJ3237】Tree(树链剖分)
题意:在一棵N个节点,有边权的树上维护以下操作: 1:单边修改,将第X条边的边权修改成Y 2:区间取反,将点X与Y在树上路径中的所有边边权取反 3:区间询问最大值,询问X到Y树上路径中边权最大值 n& ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- NetworkX学习笔记-5-NetworkX中怎样对多个网络赋属性,并根据属性排序
这是我在数据分析过程中遇到的实际问题,简单记录一下.这里以DiGraph为例,其他类型的网络(图)的处理方法是一样的. 按照这里:http://networkx.github.io/documenta ...
- Android批量图片载入经典系列——使用LruCache、AsyncTask缓存并异步载入图片
一.问题描写叙述 使用LruCache.AsyncTask实现批量图片的载入并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)载入图片,并放入缓存中 2.及时 ...
- 2013级C++第15周(春)项目——输入输出流及文件文件操作
课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759.内有完整教学方案及资源链接 本周程序阅读及程序调试中须要的文件,请到htt ...
- 给Android程序猿的六个建议
假设你一年前写的代码 , 在如今看来你还感觉写的非常不错 , 那么说明你学习的不够多. 不要在Context中持有静态引用 public class MainActivity extends Loca ...
- redis-2.6.16源码分析之pub-sub系统
redis实现的发送订阅系统,即pub-sub,这部分的的代码比较少,也方便分析.在这只将会分析下普通的pub-sub(会忽略掉Pattern-matching subscriptions),以此来简 ...
- 重叠I/O之事件通知
在 Winsock 中,重叠 I/O(Overlapped I/O)模型能达到更佳的系统性能,高于select模型.异步选择和事件选择三种.重叠模型的基本设计原理便是让应用程序使 用一个重叠的数据 ...
- 从零开始写一个Tomcat(贰)--建立动态服务器
上文书说道如何通过http协议建立一个静态的服务器来访问静态网页,但我们选择tomcat最主要的原因还是因为它能动态的执行servlet,这边文章将引导你实现一个能够运行servlet的服务器,这个简 ...
- apktool的下载地址
googlecode将要关闭,代码转移到以下网址 http://ibotpeaches.github.io/Apktool/
- C:应用于字符串处理函数
出于对C的不够熟悉,在读代码的过程中,平凡出现的字符串处理函数,成为了一个理解代码的大问题. 为了更方便的读取和理解代码,特意将接触到的字符串处理函数列出,方便查询: 1.strstr(str1,st ...
- 九宫重拍(bfs + 康拓展开)
问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12 ...