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 ...
随机推荐
- 攻防世界——web新手练习区解题总结<3>(9-12题)
第九题simple_php: 看题目说是php代码,那必定要用到php的知识,让我们先获取在线场景,得到如下网页 仔细看这个代码,意思大概是: 1.当a==0且a为真时输出flag1 2.当b为数字退 ...
- Macbook Pro HDMI 无信号解决办法
因为CS:GO无法启动的问题,使用过了下面的命令 sudo pmset -a GPUSwitch 0 导致HDMI显示器无信号 输入下面的代码 sudo pmset -a GPUSwitch 1 可以 ...
- Codehorses T-shirts (map+遍历)
Codehorses has just hosted the second Codehorses Cup. This year, the same as the previous one, organ ...
- 剑指 Offer 47. 礼物的最大价值
题目描述 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0).你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格.直到到达棋盘的右下角.给定一个棋盘及 ...
- JsonAnalyzer 源码下载
下载地址:https://files.cnblogs.com/files/heyang78/JsonAnalyzer20200518-01.zip 测试用例:https://www.cnblogs.c ...
- pwnable.kr之bof
打开题目: 先下载题目给我们的两个文件,查看文件信息: 发现没有执行的权限,所以先增加文件bof的执行权限,执行: 没发现啥,然后查看代码, #include <stdio.h> #inc ...
- 下载安装gradle
1.登录官网:www.gradle.org,进入到下图的界面: 2.点击Install Gradle,跳转到下一个界面后: 3.下载 4.下载成功后,解压到任意位置,将路径添加到path路径下,选择我 ...
- matplotlib | Python强大的作图工具,让你从此驾驭图表
今天是数据处理专题的第9篇文章,在之前的8篇文章当中我们已经介绍完了pandas这个库的一些基本用法,我们先把一些冷门的高级用法放一放,先来给大家介绍一下另外一个很有用的数据分析库--matplotl ...
- zepto | 用事件委托去解决无法给新增添的DOM添加事件的问题
前段时间在做一个任务的时候,碰见了一个问题:zepto无法用on事件去监听新增加的dom事件.这个问题用live可解决, 但是live在ios下失效,为了解决这个问题,我采用了暴力的方法去解决,每次添 ...
- (专题一)07 matlab中字符串的表示
matlab中,字符串使用单引号括起来的字符序列 >>xm='Central South University' >>xm(1:3) ans= Cen 截取1--3这三个字符, ...