QTree1 【题解】
题目背景
数据规模和spoj上有所不同
题目描述
给定一棵n个节点的树,有两个操作:
CHANGE i ti 把第i条边的边权变成ti
QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0
输入输出格式
输入格式:
第一行输入一个n,表示节点个数
第二行到第n行每行输入三个数,ui,vi,wi,分别表示 ui,vi有一条边,边权是wi
第n+1行开始,一共有不定数量行,每一行分别有以下三种可能
CHANGE,QUERY同题意所述
DONE表示输入结束
输出格式:
对于每个QUERY操作,输出一个数,表示a b之间边权最大值
输入样例:
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
输出样例:
1
3
解:
本题相较于洛谷P1505相比,操作少了许多。但是,两者单点修改有区别。此题要求修改第i条边,所以要开一个数组记录边所指向的点,而且注意,由于之前建的是双向边,所以记时i要除以二,修改时修改id[back[x]].
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#define MAXN 200010
#define inf 0x7fffffff
using namespace std;
struct node{
int nxt,to;
}e[MAXN<<1];
int head[MAXN],son[MAXN],top[MAXN],dep[MAXN];
int n,m,siz[MAXN],f[MAXN],a[MAXN],val[MAXN],xh;
int cnt,tot,id[MAXN],rk[MAXN],dt,rt,back[MAXN];
inline void swap(int &x,int &y){x^=y^=x^=y;}
char s[10];
inline int max_(int a,int b){return a>b?a:b;}
inline int min_(int a,int b){return a<b?a:b;}
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}while(ch>='0'&&ch<='9'){
s=(s<<1)+(s<<3)+(ch^48);
ch=getchar();
}return s*w;
}
struct Node{
int ls,rs,sum,tag,maxn,minn,l,r;
}tr[MAXN<<2];
inline void add(int x,int y,int w){
e[++tot].to=y;
e[tot].nxt=head[x];
head[x]=tot;
a[tot]=w;
}void dfs1(int u){
siz[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f[u])continue;
if(i%2==0)back[i/2]=v;
else back[i/2+1]=v;
f[v]=u;
val[v]=a[i];
dep[v]=dep[u]+1;
dfs1(v);
siz[u]=siz[v]+1;
if(siz[son[u]]<siz[v])son[u]=v;
}
}void dfs2(int u,int t){
top[u]=t;
rk[id[u]=++dt]=u;
if(!son[u])return;
dfs2(son[u],t);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v!=f[u]&&v!=son[u])dfs2(v,v);
}
}
#define lc tr[x].ls
#define rc tr[x].rs
inline void pushup(int x){
//tr[x].sum=tr[lc].sum+tr[rc].sum;
tr[x].maxn=max_(tr[lc].maxn,tr[rc].maxn);
//tr[x].minn=min_(tr[lc].minn,tr[rc].minn);
}
inline void pushdown(int x){
if(tr[x].tag){
tr[lc].sum=-tr[lc].sum,tr[lc].tag^=1;
tr[rc].sum=-tr[rc].sum,tr[rc].tag^=1;
int x1=tr[lc].maxn,y1=tr[lc].minn;
int x2=tr[rc].maxn,y2=tr[rc].minn;
tr[lc].maxn=-y1,tr[lc].minn=-x1;
tr[rc].maxn=-y2,tr[rc].minn=-x2;
tr[x].tag=0;
}
}
void build(int li,int ri,int &x){
x=++cnt;
tr[x].l=li;tr[x].r=ri;
if(li==ri){
tr[x].minn=tr[x].maxn=tr[x].sum=val[rk[li]];
return;
}int mid=(li+ri)>>1;
build(li,mid,lc);
build(mid+1,ri,rc);
pushup(x);
}
void change(int x,int val,int cur){
if(tr[x].l==tr[x].r){
tr[x].sum=tr[x].maxn=tr[x].minn=val;
return;
}//pushdown(x);
int mid=(tr[x].l+tr[x].r)>>1;
if(cur<=mid)change(lc,val,cur);
else change(rc,val,cur);
pushup(x);
}
void modify(int li,int ri,int x){
if(tr[x].l>=li&&tr[x].r<=ri){
tr[x].sum=-tr[x].sum,tr[x].tag^=1;
int x1=tr[x].maxn,y1=tr[x].minn;
tr[x].maxn=-y1,tr[x].minn=-x1;
return;
}pushdown(x);
int mid=(tr[x].l+tr[x].r)>>1;
if(li<=mid)modify(li,ri,lc);
if(mid<ri)modify(li,ri,rc);
pushup(x);
}
int query_s(int li,int ri,int x){
if(tr[x].l>ri||tr[x].r<li)return 0;
if(tr[x].l>=li&&tr[x].r<=ri)return tr[x].sum;
pushdown(x);
int mid=(tr[x].l+tr[x].r)>>1,ans=0;
ans=query_s(li,ri,lc)+query_s(li,ri,rc);
return ans;
}
int query_x(int li,int ri,int x){
if(tr[x].l>=li&&tr[x].r<=ri)return tr[x].maxn;
pushdown(x);
int mid=(tr[x].l+tr[x].r)>>1,ans=-inf;
if(li<=mid)ans=max_(ans,query_x(li,ri,lc));
if(mid<ri)ans=max_(ans,query_x(li,ri,rc));
return ans;
}
int query_n(int li,int ri,int x){
if(tr[x].l>=li&&tr[x].r<=ri){return tr[x].minn;}
pushdown(x);int mid=(tr[x].l+tr[x].r)>>1,ans=inf;
if(li<=mid)ans=min_(ans,query_n(li,ri,lc));
if(mid<ri)ans=min_(ans,query_n(li,ri,rc));
return ans;
}
void Segment_change(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
modify(id[fx],id[x],rt);
x=f[fx],fx=top[x];
}if(id[x]>id[y])swap(x,y);
modify(id[x]+1,id[y],rt);
}
int query(int x,int y,int ck){//ck 0sum 1max 2min
int fx=top[x],fy=top[y],ans;
if(ck==0)ans=0;else if(ck==1)ans=-inf;else ans=inf;
while(fx!=fy){
if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
if(ck==0)ans+=query_s(id[fx],id[x],rt);
else if(ck==1)ans=max_(ans,query_x(id[fx],id[x],rt));
else if(ck==2)ans=min_(ans,query_n(id[fx],id[x],rt));
x=f[fx],fx=top[x];
}if(id[x]>id[y])swap(x,y);
if(ck==0)ans+=query_s(id[x]+1,id[y],rt);
else if(ck==1)ans=max_(ans,query_x(id[x]+1,id[y],rt));
else if(ck==2)ans=min_(ans,query_n(id[x]+1,id[y],rt));
return ans;
}
int main(){dep[0]=1;
n=read();
for(register int i=1;i<n;++i){
int u=read(),v=read(),w=read();
add(u,v,w);add(v,u,w);
}dfs1(1);
dfs2(1,1);
build(1,n,rt);
while(1){
scanf("%s",s);
if(s[0]=='D')break;
int x=read(),y=read();
if(s[0]=='C')change(rt,y,id[back[x]]);
else if(s[0]=='Q'){
if(x==y)printf("0\n");
else printf("%d\n",query(x,y,1));
}
}
return 0;
}
感谢fsq dalao指教。
QTree1 【题解】的更多相关文章
- 【luogu P4114 Qtree1】 题解
题目链接:https://www.luogu.org/problemnew/show/P4114 1.把边权转化到点权:选取连接这条边的两个点中较深的一个. 2.查询点到点之间的边权时,要从seg[x ...
- QTREE系列题解
打了快一星期的qtree终于打完了- - (其实还有两题改不出来弃疗了QAQ) orz神AK一星期前就虐完QTREE 避免忘记还是简单写下题解吧0 0 QTREE1 题意: 给出一颗带边权树 一个操作 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
随机推荐
- Labview学习之路(一)程序框图中的修饰
很多小伙伴知道在前面板有很多修饰符,比如上凸框,加粗下凹框等等,但是其实在程序框图中也是有修饰符的,他的位置比较隐蔽,并且修饰符很少,所以很多人基本没有用过.现在就给大家介绍一些这些程序框图种的修饰. ...
- Python の 在 VSCode 中使用 IPython Kernel 的方法
本文介绍,在 VSCode 使用 IPython Kernel,的设置方法. 要达到的效果: 只需按下 Ctrl+:,选中的几行代码,就会自动发送到 IPython Kernel,并运行,得到结果!当 ...
- istio部署
Istio的部署介绍 目录 Istio的部署介绍 部署模型 集群模式 单集群 多集群 网络模型 单网络 多网络 控制面模型 身份和信任模型 网格中的信任 网格之间的信任 网格模型 单网格 多网格 租户 ...
- 15_Web框架-mini frame
1.WSGI协议概述(Python Web Server Gateway Interface) 1.WSGI允许开发者将选择web框架和web服务器分开,可以混合匹配web服务器和web框架,选择一个 ...
- 02_套接字编程(socket抽象层)
1.套接字概述 1.套接概述: 套接是进行网络通信的一种手段(socket) 2.套接字分类: 流式套接字(SOCK_STREAM): 传输层基于tcp协议进行通信 数 ...
- agumaster 出现实际股票数据
工程下载:https://files.cnblogs.com/files/xiandedanteng/agumaster20200430-3.zip --2020-04-30--
- Oracle WITH 语句 语法
With语句可以在查询中做成一个临时表/View,用意是在接下来的SQL中重用,而不需再写一遍. With Clause方法的优点: 增加了SQL的易读性,如果构造了多个子查询,结构会更清晰. 示例: ...
- [Java数据结构]HashSet,LinkedHashSet,TreeeSet
Java中Set表示一个不包括重复元素的集合,它有HashSet,LinkedHashSet,TreeeSet三种常用实现. HashSet是Set的最常用实现,它常被用来清除重复元素. 例程: Se ...
- xargs命令学习,于阮一峰博客
一.标准输入与管道命令 Unix 命令都带有参数,有些命令可以接受"标准输入"(stdin)作为参数. $ cat /etc/passwd | grep root 上面的代码使用了 ...
- Python远程连接Redis
import redisr=redis.Redis(host='192.168.56.102',port=6379,db=0,password='jinxfredis' )r.set('name',' ...