题目描述
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| <= 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。
题意:边权树链剖分 并维护 最大值最小值 求和 单点修改 区间取相反数
首先要考虑将边权转化为点权 如果转到父节点的话 会出现多个边在一个点的情况 所以转化为子结点 也就是深度大的结点即可
当查询 x y 询问的时候
一开始的想法:
比较x y 的深度 深度小的 转化为其儿子 然后进行查询
但是x和y的深度相同的时候 会出现问题 进一步发现 深度不同也会出错
改进:
标记跳到一条重链时的交叉结点 也就是最后一个 x=fa[top[x]]
思路应该没问题 但是很难维护最大最小值。。。
正解!!!!!
只要最后一次查询的时候(也就是跳出while后) 改为 query(id[x]+1,id[y],1,n,1) 即可
这样就会直接跳过 第二个思路那个标记点
新学会了一种维护 区间取反线段树
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 ////////////////////////////////// #define inf 0x3f3f3f3f3f3f3f3f const int N=2e5+5; ll minn[N<<2],maxx[N<<2],t[N<<2],col[N<<2],w[N],node[N]; int dep[N],top[N],fa[N],cnt,head[N],pos,siz[N],son[N],id[N],s[N][4],a,b,n,m;string ss; void up(int pos) { minn[pos]=min(minn[pos<<1],minn[pos<<1|1]); maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]); t[pos]=t[pos<<1]+t[pos<<1|1]; } void down(int pos) { if(col[pos]) { col[pos<<1]^=1; col[pos<<1|1]^=1; t[pos<<1]*=-1; t[pos<<1|1]*=-1; ll a=minn[pos<<1],b=maxx[pos<<1],c=minn[pos<<1|1],d=maxx[pos<<1|1]; minn[pos<<1]=-b;maxx[pos<<1]=-a;minn[pos<<1|1]=-d;maxx[pos<<1|1]=-c; col[pos]=0; } } void build(int l,int r,int pos) { if(l==r){t[pos]=minn[pos]=maxx[pos]=w[l];return;} int m=(l+r)>>1; build(lson);build(rson); up(pos); } void upfan(int L,int R,int l,int r,int pos) { if(L<=l&&r<=R) { int a=minn[pos],b=maxx[pos];col[pos]^=1; t[pos]*=-1;minn[pos]=-b;maxx[pos]=-a;return ; } down(pos);int m=(l+r)>>1; if(L<=m)upfan(L,R,lson); if(R>m)upfan(L,R,rson); up(pos); } void upnode(int x,int v,int l,int r,int pos) { if(l==r) { t[pos]=minn[pos]=maxx[pos]=v;return; } down(pos); int m=(l+r)>>1; if(x<=m)upnode(x,v,lson);else upnode(x,v,rson); up(pos); } ll qmax(int L,int R,int l,int r,int pos) { ll ans=-inf; if(L<=l&&r<=R)return maxx[pos]; int m=(l+r)>>1;down(pos); if(L<=m)ans=max(ans,qmax(L,R,lson)); if(R>m)ans=max(ans,qmax(L,R,rson)); up(pos);return ans; } ll qmin(int L,int R,int l,int r,int pos) { ll ans=inf; if(L<=l&&r<=R)return minn[pos]; int m=(l+r)>>1;down(pos); if(L<=m)ans=min(ans,qmin(L,R,lson)); if(R>m)ans=min(ans,qmin(L,R,rson)); up(pos);return ans; } ll qsum(int L,int R,int l,int r,int pos) { ll ans=0; if(L<=l&&r<=R)return t[pos]; ll m=(l+r)>>1;down(pos); if(L<=m)ans+=qsum(L,R,lson); if(R>m)ans+=qsum(L,R,rson); up(pos);return ans; } struct Edge { int to,nex; }edge[N]; void add(int a,int b) { edge[++pos]=Edge{b,head[a]}; head[a]=pos; } void dfs1(int x,int f,int deep) { dep[x]=deep; siz[x]=1; fa[x]=f; int maxson=-1; for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(v==f)continue; dfs1(v,x,deep+1); siz[x]+=siz[v]; if(siz[v]>maxson)maxson=siz[v],son[x]=v; } } void dfs2(int x,int topf) { id[x]=++cnt; w[cnt]=node[x]; top[x]=topf; if(!son[x])return ; dfs2(son[x],topf); for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(v==fa[x]||v==son[x])continue; dfs2(v,v); } } ll UPfan(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); upfan(id[top[x]],id[x],1,n,1); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); upfan(id[x]+1,id[y],1,n,1); } ll Qsum(int x,int y) { ll ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); ans+=qsum(id[top[x]],id[x],1,n,1); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans+=qsum(id[x]+1,id[y],1,n,1); return ans; } ll Qmin(int x,int y) { ll ans=inf; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); ans=min(ans,qmin(id[top[x]],id[x],1,n,1)); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans=min(ans,qmin(id[x]+1,id[y],1,n,1)); return ans; } ll Qmax(int x,int y) { ll ans=-inf; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); ans=max(ans,qmax(id[top[x]],id[x],1,n,1)); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans=max(ans,qmax(id[x]+1,id[y],1,n,1)); } int main() { RI(n);rep(i,1,n-1){RIII(s[i][1],s[i][2],s[i][3]); add(++s[i][1],++s[i][2]);add(s[i][2],s[i][1]); } dfs1(1,0,1); rep(i,1,n-1) { if(dep[s[i][1]]>dep[s[i][2]])node[s[i][1]]=s[i][3]; else node[s[i][2]]=s[i][3]; } dfs2(1,1);build(1,n,1);RI(m); while(m--) { cin>>ss; if(ss=="N"){RII(a,b);a++;b++;UPfan(a,b); } if(ss=="C") { RII(a,b); if(dep[s[a][1]]<dep[s[a][2]]) upnode(id[s[a][2]],b,1,n,1 ); else upnode(id[s[a][2]],b,1,n,1); } if(ss=="SUM"){RII(a,b);a++;b++; printf("%lld ",Qsum(a,b));} if(ss=="MAX"){RII(a,b);a++;b++;printf("%lld ",Qmax(a,b)); } if(ss=="MIN"){RII(a,b);a++;b++;printf("%lld ",Qmin(a,b)); } } return 0; }