洛谷P1505 [国家集训队]旅游
题目描述
\(Ray\) 乐忠于旅游,这次他来到了\(T\) 城。\(T\) 城是一个水上城市,一共有 \(N\) 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,\(T\) 城的任意两个景点之间有且只有一条路径。换句话说, \(T\) 城中只有\(N − 1\) 座桥。
\(Ray\) 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度\(w\),也就是说,\(Ray\) 经过这座桥会增加\(w\) 的愉悦度,这或许是正的也可能是负的。有时,\(Ray\) 看待同一座桥的心情也会发生改变。
现在,\(Ray\) 想让你帮他计算从\(u\) 景点到\(v\) 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
输入输出格式
输入格式:
输入的第一行包含一个整数\(N\),表示\(T\) 城中的景点个数。景点编号为 \(0...N − 1\)。
接下来\(N − 1\) 行,每行三个整数\(u\)、\(v\) 和\(w\),表示有一条u 到\(v\),使 \(Ray\) 愉悦度增加\(w\) 的桥。桥的编号为\(1...N − 1\)。\(|w| \leq 1000\)。 输入的第\(N + 1\) 行包含一个整数\(M\),表示\(Ray\) 的操作数目。
接下来有\(M\) 行,每行描述了一个操作,操作有如下五种形式:
\(C\) \(i\) \(w\),表示\(Ray\) 对于经过第\(i\) 座桥的愉悦度变成了\(w\)。
\(N\) \(u\) \(v\),表示\(Ray\) 对于经过景点\(u\) 到\(v\) 的路径上的每一座桥的愉悦度都变成原来的相反数。
\(SUM\) \(u\) \(v\),表示询问从景点\(u\) 到\(v\) 所获得的总愉悦度。
\(MAX\) \(u\) \(v\),表示询问从景点\(u\) 到\(v\) 的路径上的所有桥中某一座桥所提供的最大愉悦度。
\(MIN\) \(u\) \(v\),表示询问从景点\(u\) 到\(v\) 的路径上的所有桥中某一座桥所提供的最小愉悦度。
测试数据保证,任意时刻,\(Ray\) 对于经过每一座桥的愉悦度的绝对值小于等于\(1000\)。
输出格式:
对于每一个询问(操作\(S\)、\(MAX\) 和\(MIN\)),输出答案。
输入输出样例
输入样例#1:
3
0 1 1
1 2 2
8
SUM 0 2
MAX 0 2
N 0 1
SUM 0 2
MIN 0 2
C 1 3
SUM 0 2
MAX 0 2
输出样例#1:
3
2
1
-1
5
3
说明
很容易的基础题哦>.<
思路:如果说这道题是点权的话,那么就是一道树链剖分的板子题,但是,这道题是边权,那怎么办呢?可以发现,每个儿子只有一个父亲,那么我们就可以用这个儿子的点权来代替它与它父亲之间的边权,然后用树链剖分+线段树维护最大值,最小值和区间和即可。
代码:
#include<cstdio>
#include<algorithm>
#include<cctype>
#define maxn 200007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int inf=0x7fffffff;
int n,m,num,head[maxn],a[maxn],size[maxn],d[maxn],top[maxn];
int cnt,sum[maxn<<2],lazy[maxn<<2],maxx[maxn<<2],minn[maxn<<2];
int fa[maxn],id[maxn],zrj[maxn],son[maxn];
char s1[8];
inline int qread() {
  char c=getchar();int num=0,f=1;
  for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
  for(;isdigit(c);c=getchar()) num=num*10+c-'0';
  return num*f;
}
struct node {
  int v,w,nxt;
}e[maxn<<1];
inline void ct(int u, int v, int w) {
  e[++num].v=v;
  e[num].w=w;
  e[num].nxt=head[u];
  head[u]=num;
}
void dfs1(int u) {
  size[u]=1;
  for(int i=head[u];i;i=e[i].nxt) {
  	int v=e[i].v;
  	if(v!=fa[u]) {
  	  d[v]=d[u]+1;
  	  fa[v]=u;
  	  zrj[v]=e[i].w;
  	  dfs1(v);
  	  size[u]+=size[v];
  	  if(size[v]>size[son[u]]) son[u]=v;
	}
  }
}
void dfs2(int u, int t) {
  id[u]=++cnt;
  top[u]=t;
  a[cnt]=zrj[u];
  if(son[u]) dfs2(son[u],t);
  for(int i=head[u];i;i=e[i].nxt) {
  	int v=e[i].v;
  	if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
  }
}
inline void pushup(int rt) {
  sum[rt]=sum[ls]+sum[rs];
  maxx[rt]=max(maxx[ls],maxx[rs]);
  minn[rt]=min(minn[ls],minn[rs]);
}
inline void pushdown(int rt) {
  if(lazy[rt]) {
  	sum[ls]=-sum[ls],lazy[ls]^=1;
  	sum[rs]=-sum[rs],lazy[rs]^=1;
  	int t1=maxx[ls],t2=maxx[rs],s1=minn[ls],s2=minn[rs];
  	maxx[ls]=-s1,maxx[rs]=-s2,minn[ls]=-t1,minn[rs]=-t2;
  	lazy[rt]=0;
  }
}
void build(int rt, int l, int r) {
  if(l==r) {
  	sum[rt]=maxx[rt]=minn[rt]=a[l];
  	return;
  }
  int mid=(l+r)>>1;
  build(ls,l,mid);
  build(rs,mid+1,r);
  pushup(rt);
}
void add(int rt, int l, int r, int L, int val) {
  if(l==r) {
  	sum[rt]=maxx[rt]=minn[rt]=val;
  	return;
  }
  pushdown(rt);
  int mid=(l+r)>>1;
  if(L<=mid) add(ls,l,mid,L,val);
  else add(rs,mid+1,r,L,val);
  pushup(rt);
}
void modify(int rt, int l, int r, int L, int R) {
  if(L>r||R<l) return;
  if(L<=l&&r<=R) {
  	sum[rt]=-sum[rt],lazy[rt]^=1;
  	int t=maxx[rt],s=minn[rt];
  	maxx[rt]=-s,minn[rt]=-t;
  	return;
  }
  int mid=(l+r)>>1;
  pushdown(rt);
  modify(ls,l,mid,L,R),modify(rs,mid+1,r,L,R);
  pushup(rt);
}
int csum(int rt, int l, int r, int L, int R) {
  if(L>r||R<l) return 0;
  if(L<=l&&r<=R) return sum[rt];
  int mid=(l+r)>>1;
  pushdown(rt);
  return csum(ls,l,mid,L,R)+csum(rs,mid+1,r,L,R);
}
int cmax(int rt, int l, int r, int L, int R) {
  if(L>r||R<l) return -inf;
  if(L<=l&&r<=R) return maxx[rt];
  int mid=(l+r)>>1,ans=-inf;
  pushdown(rt);
  if(L<=mid) ans=max(ans,cmax(ls,l,mid,L,R));
  if(R>mid) ans=max(ans,cmax(rs,mid+1,r,L,R));
  return ans;
}
int cmin(int rt, int l, int r, int L, int R) {
  if(L>r||R<l) return inf;
  if(L<=l&&r<=R) return minn[rt];
  int mid=(l+r)>>1,ans=inf;
  pushdown(rt);
  if(L<=mid) ans=min(ans,cmin(ls,l,mid,L,R));
  if(R>mid) ans=min(ans,cmin(rs,mid+1,r,L,R));
  return ans;
}
void cal(int x, int y) {
  int fx=top[x],fy=top[y];
  while(fx!=fy) {
    if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
    modify(1,1,cnt,id[fx],id[x]);
    x=fa[fx],fx=top[x];
  }
  if(id[x]>id[y]) swap(x,y);
  modify(1,1,cnt,id[x]+1,id[y]);
}
int query_max(int x, int y) {
  int fx=top[x],fy=top[y],ans=-inf;
  while(fx!=fy) {
    if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
    ans=max(ans,cmax(1,1,cnt,id[fx],id[x]));
    x=fa[fx],fx=top[x];
  }
  if(id[x]>id[y]) swap(x,y);
  ans=max(ans,cmax(1,1,cnt,id[x]+1,id[y]));
  return ans;
}
int query_min(int x, int y) {
  int fx=top[x],fy=top[y],ans=inf;
  while(fx!=fy) {
    if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
    ans=min(ans,cmin(1,1,cnt,id[fx],id[x]));
    x=fa[fx],fx=top[x];
  }
  if(id[x]>id[y]) swap(x,y);
  ans=min(ans,cmin(1,1,cnt,id[x]+1,id[y]));
  return ans;
}
int query_sum(int x, int y) {
  int fx=top[x],fy=top[y],ans=0;
  while(fx!=fy) {
    if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
    ans+=csum(1,1,cnt,id[fx],id[x]);
    x=fa[fx],fx=top[x];
  }
  if(id[x]>id[y]) swap(x,y);
  ans+=csum(1,1,cnt,id[x]+1,id[y]);
  return ans;
}
int main() {
  n=qread();
  for(int i=1,u,v,w;i<n;++i) {
  	u=qread()+1,v=qread()+1,w=qread();
  	ct(u,v,w);ct(v,u,w);
  }
  dfs1(1);dfs2(1,1);build(1,1,n);
  m=qread();
  for(int i=1,x,y;i<=m;++i) {
  	scanf("%s",s1);x=qread()+1,y=qread()+1;
	if(s1[0]=='C') add(1,1,n,id[x],y-1);
	if(s1[0]=='N') cal(x,y);
	if(s1[0]=='S') printf("%d\n",query_sum(x,y));
	if(s1[1]=='I') printf("%d\n",query_min(x,y));
	if(s1[1]=='A') printf("%d\n",query_max(x,y));
  }
  return 0;
}
洛谷P1505 [国家集训队]旅游的更多相关文章
- 洛谷 P1505 [国家集训队]旅游 解题报告
		P1505 [国家集训队]旅游 题目描述 \(\tt{Ray}\) 乐忠于旅游,这次他来到了\(T\)城.\(T\)城是一个水上城市,一共有 \(N\) 个景点,有些景点之间会用一座桥连接.为了方便游 ... 
- 洛谷 P1505 [国家集训队]旅游 树链剖分
		目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1505 [国家集训队]旅游 题目描述 Ray 乐 ... 
- 2018.06.29 洛谷P1505 [国家集训队]旅游(树链剖分)
		旅游 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有 ... 
- 洛谷P1505 [国家集训队]旅游(树剖+线段树)
		传送门 这该死的码农题…… 把每一条边变为它连接的两个点中深度较浅的那一个,然后就是一堆单点修改/路径查询,不讲了 这里就讲一下怎么搞路径取反,只要打一个标记就好了,然后把区间和取反,最大最小值交换然 ... 
- [洛谷]P1505 [国家集训队]旅游
		题目链接: 传送门 题目分析: 树剖板,支持单点修改,区间取反,区间求最大值/最小值/和 区间取反取两次等于没取,维护一个\(rev\ tag\),每次打标记用\(xor\)打,记录是否需要翻转,\( ... 
- 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)
		洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ... 
- [洛谷P1527] [国家集训队]矩阵乘法
		洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ... 
- 洛谷P1501 [国家集训队]Tree II(LCT,Splay)
		洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ... 
- 洛谷P2619 [国家集训队2]Tree I(带权二分,Kruscal,归并排序)
		洛谷题目传送门 给一个比较有逼格的名词--WQS二分/带权二分/DP凸优化(当然这题不是DP). 用来解决一种特定类型的问题: 有\(n\)个物品,选择每一个都会有相应的权值,需要求出强制选\(nee ... 
随机推荐
- 菜单栏(QMenuBar)与菜单(QMenu)
			之前一直搞不清楚什么是菜单栏,后来看了文档才知道是怎么一回事,下面是我本人对菜单栏和菜单的理解,可能存在理解错误. 一.菜单栏 菜单栏是容纳菜单的一个容器,里面可以存放菜单列表,用菜单栏的目的就是为了 ... 
- SQL语言方方面面
			1 数据库和SQL 1.1 数据库 DB, DBMS DBMS的种类: 层次性数据库, 关系型数据库, 非关系型数据库 RDBMS, 关系数据库管理系统 1.2 数据库的结构 RDBMS常见的系统结构 ... 
- STL stl_config.h
			stl_config.h . // Filename: stl_config.h . . // Comment By: 凝霜 . // E-mail: mdl2009@vip.qq.com . // ... 
- CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System
			逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ... 
- mouseout与mouseleave的区别
			1 mouseout:当鼠标指针从元素上移开时,发生 mouseout 事件.该事件大多数时候会与 mouseover 事件一起使用. 2 mouseout与 mouseleave 事件不同,不论鼠标 ... 
- BZOJ1217:[HNOI2003]消防局的设立
			我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ... 
- java多线程编程核心技术——第四章总结
			第一节使用ReentrantLock类 1.1使用ReentrantLock实现同步:测试1 1.2使用ReentrantLock实现同步:测试2 1.3使用Condition实现等待/同步错误用法与 ... 
- su - user解释
			su [-fmp] [-c command] [-s shell] [--help] [--version] [-] [USER [ARG]] -c command:变更账号为USER的使用者,并执行 ... 
- Poj_1004_FinancialManagement
			一.Description Larry graduated this year and finally has a job. He's making a lot of money, but someh ... 
- Python之常用模块(二)
			shelve xml处理 configparser hashlib logging shelve模块 shelve是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持 ... 
