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. (66)zabbix导入/导出配置文件

    通过导入/导出zabbix配置文件,我们可以将自己写好的模板等配置在网络上分享,我们也可以导入网络上分享的配置文件 配置文件有两种格式,分为为xml与json,通过zabbix管理界面可以导出xml, ...

  2. Linux-Mysql8.0

    Mysql8.0.12 基本操作 解释 命令 安装服务端 yum install mysql-community-server 启动 service mysqld start/restart 停止 s ...

  3. php加密解密函数大全

    第一种: <?php function encryptDecrypt($key, $string, $decrypt){ if($decrypt){ $decrypted = rtrim(mcr ...

  4. 在linux下安装并运行scrapyd

    系统:centos7.4 安装scrapyd:pip isntall scrapyd 因为我腾讯云上是python2与python3并存的 所以我执行的命令是:pip3 isntall scrapyd ...

  5. 原来针对新唐mcu,keil有免费许可

    MDK for Nuvoton Cortex-M0/M23:The MDK for Nuvoton Cortex-M0/M23 is a license paid by Nuvoton. It is  ...

  6. hdu2604 递推转换矩阵快速幂

    刚开始还以为用位运算与或几下几个循环就搞定了,算着算着发现不行........ 还是一种固定的切题角度,我假设有长度为n,总的排列数位f(n),怎么算他呢?从后往前考虑,因为大多数情况,都是用前面的结 ...

  7. ubuntu 设置Path 开机启动脚本

    vim /etc/rc.local export PATH=$PATH:/work/apps/node-v0.12.7-linux-x64/bin:/work/apps/ledisdb/binexpo ...

  8. python基础学习笔记——面向对象初识

    面向对象初识 python中一切皆对象. 类有两种: 新式类:在py3中所有类都是新式类 经典类:在py2中只有类本身继承了object类才叫做新式类,默认是经典类 class Person: cou ...

  9. PHP函数参数传递(相对于C++的值传递和引用传递)

    学语言学得比较多了,今天突然想PHP函数传递,对于简单类型(基本变量类型)和复杂类型(类)在函数参数传递时,有没有区别呢,今天测试了下: 代码如下: <?php function test($a ...

  10. day01_14.遍历数组

    <?php $a = array('a','b','c'); print_r($a); ?> 输出结果:Array ( [0] => a [1] => b [2] => ...