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) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
随机推荐
- swift中的正则表达式
swift中的t正则表达式 正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串" ...
- Java 中的 I/O 抽象
Table of Contents 前言 字节流 常用实现 字符流 常用实现 缓冲区 各种字节流 结语 前言 由于在接触 Java 之前使用的语言是 Python,所以在转到 Java 后对 Java ...
- Linux - Shell - 常用方法 - 备忘录
$? 上一个指令的返回值 =成功,=失败 dmesg 检测系统开机启动信息 $() 对命令的替换,同`` ${} 对变量的替换,同$var $(()) 对内部内容进行整数运算 i= grep AAA ...
- java初学2
1.数组操作类Arrays与System public static void arraycopy(Object src, int srcPos, Object dest,int destPos,in ...
- 【转载】Unity3D研究院之静态自动检查代码缺陷与隐患
代码缺陷和代码错误的最大区别是,代码缺陷不影响游戏编译,而代码错误编译都不通过.但是代码缺陷会影响游戏发布后产生的一系列BUG..我今天无意间逛外国论坛发现的一个方法,使用了一下感觉挺给力的第一时间分 ...
- sql 删除重复的类型并且时间相同的项
delete RemoteDetection WHERE REMOTEDETECTIONID IN ( select ID from ( select MIN(REMOTEDETECTIONID) I ...
- 对于进程没杀死占用内存和cpu行为的方法
在跑机器学习或者深度学习的过程中有可能遇到没杀死进程的情况,但是程序的入口又没关掉,尤其是我使用jupyter从远程Linux映射到windows浏览器跑程序的时候 对于上面的问题, 首先运行 hto ...
- 架构师入门ing
算法竞赛水平一般,算法工程师估计遥遥无期,准备开始架构方面的学习. 单纯依靠垂直提升硬件性能来提高系统性能的时代已结束,分布式开发的时代实际上早已悄悄地成为了时代的主流. 在一个团队里,架构师充当了技 ...
- 华为手机怎么安装Google
华为手机怎么安装google 新买了个华为荣耀九,结果安装Google Play提示gms core 步骤一 gms 安装器.应用市场已经下架了 地址:链接: 点击打开链接 密码: m63j 步骤二 ...
- airTest 实战之 -- 【征途】自动打怪回城卖物品
airTest是一个跨平台的.基于图像识别的UI自动化测试框架,适用于游戏和App,支持平台有Windows.Android和iOS 官方文档: http://airtest.netease.com/ ...