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. go语言结构体作为函数参数,采用的是值传递

    经过验证,go语言结构体作为函数参数,采用的是值传递.所以对于大型结构体传参,考虑到值传递的性能损耗,最好能采用指针传递. 验证代码: package main import ( "fmt& ...

  2. optimize table在优化mysql时很重要

    一个表的数据量有1000W条,那么查看这么表占据的硬盘空间时会发现,数据本身是300M,索引是200M 这个时候,删除掉500W条数据,这个时候数据本身150M,而索引还是200M左右 你删除数据时, ...

  3. Page-Object思想

    为什么要使用page-object 集中管理元素对象 集中管理一个page内的公共方法 后期维护方便 集中管理元素对象 实现方法: 调用方法: WebElement element = dri ...

  4. Spring核心技术(十三)——环境的抽象

    本章将描述一下Spring中针对环境的抽象. Environment是一个集成到容器之中的特殊抽象,它针对应用的环境建立了两个关键的概念:profile和properties. profile是命名好 ...

  5. HDU 5399 数学 Too Simple

    题意:有m个1~n的映射,而且对于任意的 i 满足 f1(f2(...fm(i))) = i 其中有些映射是知道的,有些是不知道的,问一共有多少种置换的组合. 分析: 首先这些置换一定是1~n的一个置 ...

  6. struts2对properties资源的处理

    struts2对properties资源的处理 做了一些功能增强 包括: 可以读取项的描述 可以读取项所在的行号,文件路径等 实现方式 继承了java的java.util.Properties实现了一 ...

  7. Python的深浅copy

    27.简述Python的深浅拷贝以及应用场景? 深浅拷贝的原理 深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:copy.deepcopy 字面理 ...

  8. day04_09 while循环03

    练习题: 3.如何输入一个如下的直角三角形,用户指定输出行数:(如果上下反转,右如何实现?) ********** 以下是自己的思路,没有按照上课老师的思路,反正经过不断的测试改进得出的算法 num ...

  9. 聊聊、Java Keytool P12 转 JKS

    最近公司合作机构需要更改服务证书,总共给了 3 个文件过来.openapi-cert.p12.openapi-cert.key.openapi-cert.crt. openapi-cert.crt - ...

  10. Apache Log4j 2 is Coming

    刚刚从同事那里得知,log4j 2 出beta版本了. 有啥提升呢? Improved PerformanceLog4j 2 contains next-generation Asynchronous ...