题目背景

数据规模和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 【题解】的更多相关文章

  1. 【luogu P4114 Qtree1】 题解

    题目链接:https://www.luogu.org/problemnew/show/P4114 1.把边权转化到点权:选取连接这条边的两个点中较深的一个. 2.查询点到点之间的边权时,要从seg[x ...

  2. QTREE系列题解

    打了快一星期的qtree终于打完了- - (其实还有两题改不出来弃疗了QAQ) orz神AK一星期前就虐完QTREE 避免忘记还是简单写下题解吧0 0 QTREE1 题意: 给出一颗带边权树 一个操作 ...

  3. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  4. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  5. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  6. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  7. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  8. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  9. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

随机推荐

  1. P4719 【模板】"动态 DP"&动态树分治

    题目描述 给定一棵 n 个点的树,点带点权. 有 m 次操作,每次操作给定 x,y,表示修改点 x 的权值为 y. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 输入格式 第一行有两个整数 ...

  2. 盒子上下滚动到js 底部触发的事件

    //html是用法举列子,js亲测有效(把这段js#scro加到你要滚动的盒子) <div id="scro">  <div>1</div> & ...

  3. 良许被百万大V安排得服服帖帖,还跟美女小姐姐合影了……

    大家好,我是良许. 很多人问我说,良许,你在工作之余还花这么多时间精力去写公众号运营自媒体,到底是为了什么? 其实原因很简单,就是想做个副业,万一到了 35 岁真的失业了,我至少还有另外一份收入,不至 ...

  4. HDU-4417-Super Mario(主席树解法)

    Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory ...

  5. JVM—01

    目录 1.1 JVM系统架构图 2.1 类加载器 2.1.1 双亲委派机制 2.1.2 沙箱安全机制 3.1 Native 4.1 PC寄存器 1.1 JVM系统架构图 JVM是什么? JVM是Jav ...

  6. <init>与<clinit>,static与final与static final

    <init>和<clinit> init是对象构造器方法,初始化对象的时候执行 clinit是类构造器方法,类加载的初始化阶段执行 final常量赋值(必须是一下其中一种) 显 ...

  7. RabbitMQ安装和运行

    RabbitMQ在Windows下安装和运行 1.下载Erlang: http://www.erlang.org/downloads/19.2 2.下载Windows版RabbitMq: http:/ ...

  8. 推荐掌握Linux shell中这7种运算命令

    #常见的算术运算符号 .+.-:加减 .*./.%:乘.除.取余 .**:幂运算 .++.--:增加记减少 .!.&&.||:取反,并且,或 .<,<=,>,=> ...

  9. LiteOS间歇计算技术:IOT终端真正感受“电量自由”

    摘要:LiteOS间歇计算为什么能使物联网终端实现长续航? 物联网设备.场景复杂多样,小到智能穿戴的耳机,大到大型基建设备,更有我们陌生而又熟悉场景,例如深海探测.森林监控.野生动物跟踪等等能量采集场 ...

  10. C语言知识点汇集

    int main() {// int num; int value; = int num,value; '''同时定义多个变量的方法 但是切记只能是同种类型的''' 都是int 或double等其他类 ...