Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 9233   Accepted: 2431

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 ≤ 100,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

Source

 
思路:
  树剖边权转点权;
  边权赋值到边上深度较大的点;
  然后有个取反操作,就是相反数;
  我们记录max和min;
  每次取反交换max和min;
  然后乘以-1;
  轻松ac(不知道wa了多少次);
 
来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define maxn 1000005 using namespace std; struct TreeNodeType {
int l,r,dis,dis_,mid,flag;
};
struct TreeNodeType tree[maxn<<]; struct EdgeType {
int v,w,next;
};
struct EdgeType edge[maxn<<]; int u_[maxn],v_[maxn];
int if_z,t,n,cnt,head[maxn],deep[maxn],f[maxn];
int flag[maxn],top[maxn],size[maxn],dis[maxn],dis_[maxn]; char Cget; inline void in(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int u,int v,int w)
{
edge[++cnt].v=v,edge[cnt].w=w,edge[cnt].next=head[u],head[u]=cnt;
edge[++cnt].v=u,edge[cnt].w=w,edge[cnt].next=head[v],head[v]=cnt;
} void search_1(int now,int fa)
{
int pos=cnt++;
deep[now]=deep[fa]+,f[now]=fa;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].v==fa) continue;
dis_[edge[i].v]=edge[i].w;
search_1(edge[i].v,now);
}
size[now]=cnt-pos;
} void search_2(int now,int chain)
{
int pos=;
top[now]=chain;
flag[now]=++cnt;
dis[flag[now]]=dis_[now];
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].v==f[now]) continue;
if(size[edge[i].v]>size[pos]) pos=edge[i].v;
}
if(pos==) return ;
search_2(pos,chain);
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].v==f[now]||edge[i].v==pos) continue;
search_2(edge[i].v,edge[i].v);
}
} inline void tree_up(int now)
{
tree[now].dis=max(tree[now<<].dis,tree[now<<|].dis);
tree[now].dis_=min(tree[now<<].dis_,tree[now<<|].dis_);
} inline void tree_down(int now)
{
if(tree[now].l==tree[now].r) return ;
tree[now<<].dis*=-,tree[now<<|].dis*=-;
tree[now<<].dis_*=-,tree[now<<|].dis_*=-;
tree[now<<].flag*=-,tree[now<<|].flag*=-;
swap(tree[now<<].dis_,tree[now<<].dis);
swap(tree[now<<|].dis_,tree[now<<|].dis);
tree[now].flag=;return ;
} void tree_build(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r,tree[now].flag=;
if(l==r)
{
tree[now].dis=dis[l];
tree[now].dis_=tree[now].dis;
return ;
}
tree[now].mid=(l+r)>>;
tree_build(now<<,l,tree[now].mid);
tree_build(now<<|,tree[now].mid+,r);
tree_up(now);
} void tree_change(int now,int to,int x)
{
if(tree[now].l==tree[now].r)
{
tree[now].dis=x;
tree[now].dis_=x;
return ;
}
if(tree[now].flag==-) tree_down(now);
if(to<=tree[now].mid) tree_change(now<<,to,x);
else tree_change(now<<|,to,x);
tree_up(now);
} void tree_negate(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r)
{
tree[now].dis*=-;
tree[now].dis_*=-;
swap(tree[now].dis,tree[now].dis_);
tree[now].flag*=-;
return ;
}
if(tree[now].flag==-) tree_down(now);
if(l>tree[now].mid) tree_negate(now<<|,l,r);
else if(r<=tree[now].mid) tree_negate(now<<,l,r);
else
{
tree_negate(now<<,l,tree[now].mid);
tree_negate(now<<|,tree[now].mid+,r);
}
tree_up(now);
} int tree_query(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r)
{
return tree[now].dis;
}
if(tree[now].flag==-) tree_down(now);
if(l>tree[now].mid) return tree_query(now<<|,l,r);
else if(r<=tree[now].mid) return tree_query(now<<,l,r);
else
{
return max(tree_query(now<<,l,tree[now].mid),tree_query(now<<|,tree[now].mid+,r));
}
} int solve_query(int x,int y)
{
int pos=-0x7ffffff;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
pos=max(pos,tree_query(,flag[top[x]],flag[x]));
x=f[top[x]];
}
if(x==y) return pos;
if(deep[x]>deep[y]) swap(x,y);
pos=max(pos,tree_query(,flag[x]+,flag[y]));
return pos;
} void solve_negate(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
tree_negate(,flag[top[x]],flag[x]);
x=f[top[x]];
}
if(x==y) return ;
if(deep[x]>deep[y]) swap(x,y);
tree_negate(,flag[x]+,flag[y]);
} int main()
{
in(t);
while(t--)
{
memset(head,,sizeof(head));
in(n);cnt=;
int u,v,w;char ch[];
for(int i=;i<n;i++)
{
in(u),in(v),in(w);
u_[i]=u,v_[i]=v,edge_add(u,v,w);
}
cnt=,search_1(,);
cnt=,search_2(,);
tree_build(,,n);
for(int i=;i<n;i++)
{
if(deep[u_[i]]<deep[v_[i]]) swap(u_[i],v_[i]);
}
while()
{
cin>>ch;
if(ch[]=='D') break;
in(u),in(v);
if(ch[]=='N') solve_negate(u,v);
if(ch[]=='C') tree_change(,flag[u_[u]],v);
if(ch[]=='Q')
{
cout<<solve_query(u,v);
putchar('\n');
}
}
}
return ;
}

AC日记——Tree poj 3237的更多相关文章

  1. AC日记——Crane poj 2991

    POJ - 2991 思路: 向量旋转: 代码: #include <cmath> #include <cstdio> #include <cstring> #in ...

  2. AC日记——Dividing poj 1014

    Dividing Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 69575   Accepted: 18138 Descri ...

  3. AC日记——pigs poj 1149

    POJ - 1149 思路: 最大流: 代码: #include <cstdio> #include <cstring> #include <iostream> # ...

  4. AC日记——Dining poj 3281

    [POJ-3281] 思路: 把牛拆点: s向食物连边,流量1: 饮料向t连边,流量1: 食物向牛1连边,流量1: 牛2向饮料连边,流量1: 最大流: 来,上代码: #include <cstd ...

  5. AC日记——Two poj 1849

    Two 思路: 树形DP求直径: 答案是边权总和*2-直径: dp[i][1]::以i为根的子树中最长的路径: dp[i][0]::以i为根的子树中次长的路径: 来,上代码: #include < ...

  6. AC日记——Oulipo poj 3461

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37958   Accepted: 15282 Description The ...

  7. poj 3237 Tree [LCA] (树链剖分)

    poj 3237 tree inline : 1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高. 2. 很明显,类 ...

  8. poj 3237 Tree(树链拆分)

    题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...

  9. cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

    1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 ...

随机推荐

  1. Inkscape基础

    What is Inkscape A program for creating vector graphics For Windows, Mac OS, and Linux Open source F ...

  2. kali添加更新源

    /etc/apt/sources.list 具体方法参考: http://blog.csdn.net/gmnet/article/details/14471835 http://blog.sina.c ...

  3. python入门:模拟简单用户登录(自写)

    #!/usr/bin/env python # -*- coding: utf-8 -*- #模拟简单用户登录(自写) import getpass a = raw_input("Pleas ...

  4. 【linux】文件默认权限:umask

    在默认权限的属性上,目录与文件是不一样的.从第六章我们知道 x 权限对於目录是非常重要的! 但是一般文件的创建则不应该有运行的权限,因为一般文件通常是用在於数据的记录嘛!当然不需要运行的权限了. 因此 ...

  5. 用Python手把手教你搭建一个web框架-flask微框架!

    在之前的文章当中,小编已经教过大家怎么搭建一个Django框架,今天我们来探索另外的一种框架的搭建,这个框架就是web框架-flask微框架啦!首先我们带着以下的几个问题来阅读本文: 1.flask是 ...

  6. Python基础-面向对象初识--类

    什么是类 具有相似功能和属性的一类实物 什么是对象 类的具体体现,具体到一个 面向对象的优势 1.类是一组相似功能的集合,使组织结构更加清晰和规范化 2.研究面向对象要有上帝的思维,用面向对象设计程序 ...

  7. 杭电 1155 Bungee Jumping(物理题)

    Problem Description Once again, James Bond is fleeing from some evil people who want to see him dead ...

  8. 字符串:HDU3064-最长回文

    最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Descri ...

  9. hdu 5459

    Problem Description I've sent Fang Fang around 201314 text messages in almost 5 years. Why can't she ...

  10. 在spring boot中使用webSocket组件(二)

    该篇演示如何使用websocket创建一对一的聊天室,废话不多说,我们马上开始! 一.首先先创建前端页面,代码如下图所示: 1.login.html <!DOCTYPE html> < ...