LUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)
解题思路
快被调死的码农题,,,其实就是一个边权下放到点权的线段树+树剖。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib> using namespace std;
const int MAXN = ;
const int inf = 0x3f3f3f3f; inline int rd(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {f=ch=='-'?:;ch=getchar();}
while(isdigit(ch)) {x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
} int n,m,head[MAXN],cnt=,to[MAXN<<],nxt[MAXN<<],val[MAXN<<],num;
int w[MAXN],wt[MAXN],id[MAXN],top[MAXN],siz[MAXN],son[MAXN],fa[MAXN],dep[MAXN];
int Sum[MAXN<<],Min[MAXN<<],Max[MAXN<<];
bool rev[MAXN<<],lazy[MAXN<<]; inline void add(int bg,int ed,int ww){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt,val[cnt]=ww;
} void dfs1(int x,int f,int d){
dep[x]=d,fa[x]=f,siz[x]=;int maxson=-,u;
for(register int i=head[x];i;i=nxt[i]){
u=to[i];if(u==f) continue;
dfs1(u,x,d+);siz[x]+=siz[u];w[u]=val[i];
if(siz[u]>maxson) {maxson=siz[u];son[x]=u;}
}
} void dfs2(int x,int topf){
top[x]=topf;id[x]=++num;wt[num]=w[x];
if(!son[x]) return;dfs2(son[x],topf);int u;
for(register int i=head[x];i;i=nxt[i]){
u=to[i];if(u==fa[x] || u==son[x]) continue;
dfs2(u,u);
}
} inline void pushdown(int x){
rev[x<<]^=;rev[x<<|]^=;rev[x]^=;
Sum[x<<]=-Sum[x<<];Sum[x<<|]=-Sum[x<<|];
swap(Min[x<<],Max[x<<]);swap(Min[x<<|],Max[x<<|]);
Min[x<<]=-Min[x<<];Min[x<<|]=-Min[x<<|];
Max[x<<]=-Max[x<<];Max[x<<|]=-Max[x<<|];
} void build(int x,int l,int r){
if(l==r) {if(l==) Min[x]=inf,Max[x]=-inf; else Sum[x]=Min[x]=Max[x]=wt[l];return;}
int mid=(l+r)>>;
build(x<<,l,mid);build(x<<|,mid+,r);
Sum[x]=Sum[x<<]+Sum[x<<|];
Min[x]=min(Min[x<<],Min[x<<|]);
Max[x]=max(Max[x<<],Max[x<<|]);
} void update(int x,int l,int r,int L,int R,int ww){
if(L<=l && r<=R) {
if(ww==-inf) {rev[x]^=;Sum[x]=-Sum[x];swap(Min[x],Max[x]);Min[x]=-Min[x];Max[x]=-Max[x];}
else Sum[x]=Min[x]=Max[x]=ww;
return;
}
int mid=(l+r)>>;if(rev[x]) pushdown(x);
if(L<=mid) update(x<<,l,mid,L,R,ww);
if(mid<R) update(x<<|,mid+,r,L,R,ww);
Sum[x]=Sum[x<<]+Sum[x<<|];
Min[x]=min(Min[x<<],Min[x<<|]);
Max[x]=max(Max[x<<],Max[x<<|]);
} int query_Sum(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return Sum[x];
int mid=(l+r)>>,ret=;if(rev[x]) pushdown(x);
if(L<=mid) ret+=query_Sum(x<<,l,mid,L,R);
if(mid<R) ret+=query_Sum(x<<|,mid+,r,L,R);
return ret;
} int query_Max(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return Max[x];
int mid=(l+r)>>,ret=-inf;if(rev[x]) pushdown(x);
if(L<=mid) ret=max(ret,query_Max(x<<,l,mid,L,R));
if(mid<R) ret=max(ret,query_Max(x<<|,mid+,r,L,R));
return ret;
} int query_Min(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return Min[x];
int mid=(l+r)>>,ret=inf;if(rev[x]) pushdown(x);
if(L<=mid) ret=min(ret,query_Min(x<<,l,mid,L,R));
if(mid<R) ret=min(ret,query_Min(x<<|,mid+,r,L,R));
return ret;
} void updRev(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(,,n,id[top[x]],id[x],-inf);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) update(,,n,id[x]+,id[y],-inf);
} inline int qSum(int x,int y){
int ret=;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret+=query_Sum(,,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) ret+=query_Sum(,,n,id[x]+,id[y]);
return ret;
} inline int qMax(int x,int y){
int ret=-inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret=max(ret,query_Max(,,n,id[top[x]],id[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) ret=max(ret,query_Max(,,n,id[x]+,id[y]));
return ret;
} inline int qMin(int x,int y){
int ret=inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret=min(ret,query_Min(,,n,id[top[x]],id[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);if(x!=y) ret=min(ret,query_Min(,,n,id[x]+,id[y]));
return ret;
} inline int pre(int x){
return dep[to[x<<]]>dep[to[x<<^]]?to[x<<]:to[x<<^];
} int main(){
// freopen("wrong.out","w",stdout);
n=rd();int x,y,z;char s[];
for(int i=;i<n;i++){
x=rd()+,y=rd()+,z=rd();
add(x,y,z),add(y,x,z);
}
dfs1(,,);dfs2(,);build(,,n);m=rd();
while(m--){
scanf("%s",s+);x=rd(),y=rd();
if(s[]=='C') update(,,n,id[pre(x)],id[pre(x)],y);
else if(s[]=='N') updRev(x+,y+);
else if(s[]=='S') printf("%d\n",qSum(x+,y+));
else if(s[]=='A') printf("%d\n",qMax(x+,y+));
else printf("%d\n",qMin(x+,y+));
}
return ;
}
LUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)的更多相关文章
- BZOJ2157旅游——树链剖分+线段树
题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- 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 ...
随机推荐
- TCP/IP点滴
1 子网的划分 2 子网的表述 ipv4 IPv4中规定IP地址长度为32,最大地址个数为2^32,点分十进制表示方法:122.70.156.25. ipv6 地址的长度为128,即最大地址个数为2^ ...
- 关于Mysql分区和分表
[分区概念]分区就是把一张表的数据按照一定的规则分成多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上.分区后表还是一张表.分区根据一定的规则把数据文件和索引文件进行了分割,还多出了一个.pa ...
- 《DSP using MATLAB》Problem 9.2
前几天看了看博客,从16年底到现在,3年了,终于看书到第9章了.都怪自己愚钝不堪,唯有吃苦努力,一点一点一页一页慢慢啃了. 代码: %% ------------------------------- ...
- python中面向对象
一.Python经典类与新类 经典类:如果没有直接或间接的子类化一个对象,也就是说如果没有指定一个父类,或者是如果子类化的基本类没有父类,那么就定义了经典类: class classics: 'def ...
- String 字符串对象
String是什么 String字符串,是一种引用数据类型,并不是基础数据类型. 对于基础数据类型和引用数据类型的区别: 基础数据类型,在创建时直接将值存放在栈内存中. 引用数据类型,在创建时栈内存中 ...
- Linux系统搭建Red5服务器
Linux系统搭建Red5服务器 Red5 是 支持Windows,Linux等多平台的RTMP流媒体服务器,Windows下搭建相对容易,图形界面操作比较简单,Linux服务器的环境下没有图形界面, ...
- 【leetcode题目整理】数组中找子集
368. Largest Divisible Subset 题意:找到所有元素都不同的数组中满足以下规则的最大子集,规则为:子集中的任意两个元素a和b,满足a%b=0或者b%a=0. 解答:利用动态规 ...
- linux zip,tar压缩文件夹 忽略 .git 文件夾
linux zip 忽略 .git 文件夾 # zip 命令 zip -r bitvolution.zip bitvolution -x *.git* # tar命令压缩文件夹忽略 .git文件夹 t ...
- 学习mysql水平分区和实践笔记
SHOW PLUGINS; sql 可以查看partition的Status 是否是ACTIVE的 使用mydatetime 进行水平分区案例: CREATE TABLE test_users ( ` ...
- linux dmesg命令使用
linux dmesg命令使用 2012-11-27 09:37 2783人阅读 评论(0) 收藏 举报 分类: linux内核与编程(199) 版权声明:本文为博主原创文章,未经博主允许不得转载 ...