HDU 3237 Tree(树链剖分)(线段树区间取反,最大值)
| Time Limit: 5000MS | Memory Limit: 131072K | |
| Total Submissions: 9123 | Accepted: 2411 |
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
【分析】题意很好理解,唯一的难点就是将某一区间内的数变成相反数,需要用到懒惰标记。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N=2e5+;
const int M=N*N+;
int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N]; //top 最近的重链父节点
int num,s,m,n,q;
int sum[N*],tre[*N];
int maxn[N],minn[N],lazy[N];
vector<int> v[N];
struct tree {
int x,y,val;
void read() {
scanf("%d%d%d",&x,&y,&val);
}
} e[N];
void dfs1(int u, int f, int d) {
dep[u] = d;
siz[u] = ;
son[u] = ;
fa[u] = f;
for (int i = ; i < v[u].size(); i++) {
int ff = v[u][i];
if (ff == f) continue;
dfs1(ff, u, d + );
siz[u] += siz[ff];
if (siz[son[u]] < siz[ff])
son[u] = ff;
}
}
void dfs2(int u, int tp) {
top[u] = tp;
id[u] = ++num;
if (son[u]) dfs2(son[u], tp);
for (int i = ; i < v[u].size(); i++) {
int ff = v[u][i];
if (ff == fa[u] || ff == son[u]) continue;
dfs2(ff, ff);
}
}
void ChangeVal(int rt) {
int tmp=maxn[rt];
maxn[rt]=-minn[rt];
minn[rt]=-tmp;
}
void Push_up(int rt) {
maxn[rt]=max(maxn[*rt],maxn[*rt+]);
minn[rt]=min(minn[*rt],minn[*rt+]);
}
void Push_down(int rt) {
if(lazy[rt]) {
lazy[rt]^=;
lazy[*rt]^=;
ChangeVal(rt*);
lazy[*rt+]^=;
ChangeVal(*rt+);
}
}
void change(int t,int l,int r,int x,int v){
if(l==r) maxn[t]=minn[t]=v;
else{
Push_down(t);
int mid=(l+r)>>;
if(x<=mid) change(t*,l,mid,x,v);
else change(t*+,mid+,r,x,v);
Push_up(t);
}
}
void Build(int l,int r,int rt) {
if(l==r) {
maxn[rt]=minn[rt]=val[l];
return;
}
int m=(l+r)>>;
Build(lson);
Build(rson);
Push_up(rt);
//printf("rt=%d sum[rt]=%d\n",rt,sum[rt]);
} void Update(int L,int R,int l,int r,int rt) {
if(l>=L&&r<=R) {
lazy[rt]^=;
ChangeVal(rt);
return;
}
Push_down(rt);
int m=(r+l)>>;
if(L<=m)Update(L,R,lson);
if(R>m) Update(L,R,rson);
Push_up(rt);
} int Query(int L,int R,int l,int r,int rt) {
if(L<=l&&r<=R)return maxn[rt];
Push_down(rt);
int m=(l+r)>>;
if(R<=m)return Query(L,R,lson);
else if(L>m)return Query(L,R,rson);
else return max(Query(L,m,lson),Query(m+,R,rson));
} void solve(int u, int v) {
int tp1 = top[u], tp2 = top[v];
int ans = ;
while (tp1 != tp2) {
if (dep[tp1] < dep[tp2]) {
swap(tp1, tp2);
swap(u, v);
}
Update(id[tp1],id[u],,n,);
u = fa[tp1];
tp1 = top[u];
}
if (u == v) return;
if (dep[u] > dep[v]) swap(u, v);
Update(id[son[u]],id[v],,n,);
return;
}
int Yougth(int u,int v) {
int tp1 = top[u], tp2 = top[v];
int ans=-;
while (tp1 != tp2) {
if (dep[tp1] < dep[tp2]) {
swap(tp1, tp2);
swap(u, v);
}
ans = max(Query(id[tp1], id[u],,n,),ans);
u = fa[tp1];
tp1 = top[u];
}
if (u == v) return ans;
if (dep[u] > dep[v]) swap(u, v);
ans = max(Query(id[son[u]], id[v],,n,),ans);
return ans;
}
void Clear(int n) {
for(int i=; i<=n; i++)
v[i].clear();
met(son,);met(maxn,);met(minn,);
met(lazy,);
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
Clear(n);
int u,vv,w;
for(int i=; i<n; i++) {
e[i].read();
v[e[i].x].push_back(e[i].y);
v[e[i].y].push_back(e[i].x);
}
num = ;
dfs1(,,);
dfs2(,);
for (int i = ; i < n; i++) {
if (dep[e[i].x] < dep[e[i].y]) swap(e[i].x, e[i].y);
val[id[e[i].x]] = e[i].val;
}
Build(,num,);
char str[];
while(~scanf("%s",str)) {
if(str[]=='D')break;
if(str[]=='C') {
scanf("%d%d",&u,&vv);
if(dep[e[u].x]<dep[e[u].y])swap(e[u].x,e[u].y);
change(,,n,id[e[u].x],vv);
} else if(str[]=='N'){
scanf("%d%d",&u,&vv);
solve(u,vv);
}else {
scanf("%d%d",&u,&vv);
if(u==vv)puts("");
else printf("%d\n",Yougth(u,vv));
}
} } return ;
}
HDU 3237 Tree(树链剖分)(线段树区间取反,最大值)的更多相关文章
- 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 ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- 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, ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
随机推荐
- 关于JavaScript设计模式的学习(二)
第二部分来了,是关于结构型的,同样的,还是在简书中,GitHub上也有代码示例和详细注释 简书:http://www.jianshu.com/p/face1be4b846 github:https:/ ...
- 程序员必备PC维修法(硬件篇)
自检自修不是万能,但不会自检自修却万万不能.程序员修电脑还是有必要的. 情景:通电情况下,电脑主机无法启动,所有主机内部硬件无反应. 原因:1.CPU.主板.电源积尘.(出现率30%) 2.CPU.主 ...
- Centos/linux开放端口
在linux上部署tomcat发现外部无法访问可以通过两种方式解决: 1.关闭防火墙 service iptables stop(不推荐) 2.修改相关文件,开放需要开放的端口 (1)通过命令vi / ...
- js 全局变量和局部变量
Javascript在执行前会对整个脚本文件的声明部分做完整分析(包括局部变量),但是不能对变量定义做提前解析 1.作用域和作用域链 2.变量声明提前
- operator、explicit与implicit
说这个之前先说下什么叫隐式转换和显示转换 1.所谓隐式转换,就是系统默认的转换,其本质是小存储容量数据类型自动转换为大存储容量数据类型. 例如:float f = 1.0: double d=f:这样 ...
- HDU 4109 Instrction Arrangement(DAG上的最长路)
把点编号改成1-N,加一点0,从0点到之前任意入度为0的点之间连一条边权为0的边,求0点到所有点的最长路. SPFA模板留底用 #include <cstdio> #include < ...
- ASP.NET——实现两个下拉框动态联动
引入: 在网页中,我们经常会遇到下图中的情况.首先在下拉框中选择所在的省,选择之后,第二个下拉框会自动加载出该省中的市.这样设计极大的方便了用户的查找.那这是如何实现的呢? 1.建立数据库 " ...
- 29个android开发常用的类、方法及接口
在安卓开发中,我们常常都需要借助各种各样的方法.类和接口来实现相关功能.提升开发效率,但对于初学者而言,什么时候该用什么类.方法和接口呢?下面小编整理了29个,日常开发中比较常用的类.方法.接口及其应 ...
- altium designer同一工程多个原理图如何快速查找同一网络标号
方法一:如果只知道网络标号的名称,尚未找到任何一个,可以:Ctrl+F,输入网络标号名称,可按顺序逐个查看各个网络标号. 方法二:如果已经看到一个所要查找的网络标号,可以:按住Alt键不放,鼠标左键单 ...
- [洛谷P1903][国家集训队]数颜色
题目大意:有$n$支画笔,有两个操作 $Q\;l\;r:$询问$[l,r]$中有几种颜色 $R\;p\;Col:$把第$p$支画笔的颜色改成$Col$ 题解:带修莫队,分为$n^{\frac{1}{3 ...