P1505 [国家集训队]旅游
分析
这题和P4114 Qtree1这道题目非常之类似。其中关于如何将边权转化为点权并维护在Qtree1的题解中,需要请看这里题解。
在Qtree1这道题目里面,我们只需要维护最大值即可。
但在旅游这道题中,我们需要维护最小值,最大值,总和。
但这都不是最麻烦的,最麻烦是将一个区间的值全变为其相反数。
难道真的要,依次一个一个的变为对应的相反数嘛?
当然不用,我们有一个常见的小技巧,在面对这类数据结构问题时。
加入懒标记tag,标注此时该区间是否发生了性质的转换
例如,当要求我们,在一个双向链表中,插入,删除,翻转链表时。
我们就会使用懒标记,当插入时,懒标记处于翻转状态,我们就反着插入。
在此题中也是类似。
(线段树结点结构体)
struct Node
{
int l,r,mmax,mmin,sum,tag;
}tr[N<<2];
我们加入懒标记tag,标记此区间内的所有边权是否发生了翻转。
若发生翻转,那此时区间最大值变最小值,最小值变最大值,总和变为相反数
那pushdown函数长什么样子呢
void pushdown(int u)
{
auto &root = tr[u],&left = tr[u<<1],&right = tr[u<<1|1];
if(root.tag)
{
left.tag ^= root.tag;
change(left);
right.tag ^= root.tag;
change(right);
root.tag = 0;
}
}
其中的change函数,就是对区间的翻转操作
void change(Node &u)
{
swap(u.mmax,u.mmin);
u.mmax = -u.mmax,u.mmin = -u.mmin;
u.sum = -u.sum;
}
其他的操作就是正常的树剖和线段树了;
其中对于将边权变为点权后,从u->v的路径中,对LCA的处理,请务必看一下Qtree1
AC_code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10,M = N*2;
struct Node
{
int l,r,mmax,mmin,sum,tag;
}tr[N<<2];
int h[N],e[M],ne[M],w[M],idx;
int id[N],nw[N],top[N],ts;
int son[N],fa[N],val[N],e2u[N],dep[N],sz[N];
int n;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
void dfs1(int u,int pa,int depth)
{
sz[u] = 1,fa[u] = pa,dep[u] = depth;
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==pa) continue;
val[j] = i/2+1;
e2u[i/2+1] = j;
dfs1(j,u,depth+1);
if(sz[son[u]]<sz[j]) son[u] = j;
sz[u] += sz[j];
}
}
void dfs2(int u,int tp)
{
id[u] = ++ts,top[u] = tp,nw[ts] = w[val[u]];
if(!son[u]) return ;
dfs2(son[u],tp);
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==son[u]||j==fa[u]) continue;
dfs2(j,j);
}
}
void pushup(int u)
{
tr[u].mmax = max(tr[u<<1].mmax,tr[u<<1|1].mmax);
tr[u].mmin = min(tr[u<<1].mmin,tr[u<<1|1].mmin);
tr[u].sum = tr[u<<1].sum + tr[u<<1|1].sum;
}
void change(Node &u)
{
swap(u.mmax,u.mmin);
u.mmax = -u.mmax,u.mmin = -u.mmin;
u.sum = -u.sum;
}
void pushdown(int u)
{
auto &root = tr[u],&left = tr[u<<1],&right = tr[u<<1|1];
if(root.tag)
{
left.tag ^= root.tag;
change(left);
right.tag ^= root.tag;
change(right);
root.tag = 0;
}
}
void build(int u,int l,int r)
{
if(l==r)
{
tr[u] = {l,r,nw[l],nw[l],nw[l],0};
return ;
}
tr[u] = {l,r,0,0,0,0};
int mid = l + r >> 1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,bool f,int k2)
{
if(l<=tr[u].l&&tr[u].r<=r)
{
if(!f) tr[u].mmax = tr[u].mmin = tr[u].sum = k2;
else change(tr[u]),tr[u].tag ^= 1;
return ;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l<=mid) modify(u<<1,l,r,f,k2);
if(r>mid) modify(u<<1|1,l,r,f,k2);
pushup(u);
}
int query(int u,int l,int r,int type)
{
// cout<<u<<" "<<tr[u].l<<" "<<tr[u].r<<endl;
if(l<=tr[u].l&&tr[u].r<=r)
{
if(type==1) return tr[u].sum;
if(type==2) return tr[u].mmax;
return tr[u].mmin;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
int res = 0;
if(type==2) res = -1e9;
if(type==3) res = 1e9;
if(l<=mid)
{
if(type==1) res += query(u<<1,l,r,type);
if(type==2) res = max(res,query(u<<1,l,r,type));
if(type==3) res = min(res,query(u<<1,l,r,type));
}
if(r>mid)
{
if(type==1) res += query(u<<1|1,l,r,type);
if(type==2) res = max(res,query(u<<1|1,l,r,type));
if(type==3) res = min(res,query(u<<1|1,l,r,type));
}
pushup(u);
return res;
}
int main()
{
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++)
{
int a,b,c;cin>>a>>b>>c;
a++,b++;
w[i+1] = c;
add(a,b),add(b,a);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);
int m;cin>>m;
while(m--)
{
string s;cin>>s;
int x,y,res;cin>>x>>y;
if(s=="C") modify(1,id[e2u[x]],id[e2u[x]],0,y);
else if(s=="N")
{
x++,y++;
if(x==y) continue;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
modify(1,id[top[x]],id[x],1,0);
x = fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
modify(1,id[y]+1,id[x],1,0);
}
else if(s=="SUM")
{
x++,y++;
res = 0;
if(x==y) puts("0");
else
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res+=query(1,id[top[x]],id[x],1);
x = fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
res += query(1,id[y]+1,id[x],1);
printf("%d\n",res);
}
}
else if(s=="MAX")
{
x++,y++;
res = -1e9;
if(x==y) puts("0");
else
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res= max(res,query(1,id[top[x]],id[x],2));
x = fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
res = max(res,query(1,id[y]+1,id[x],2));
printf("%d\n",res);
}
}
else
{
x++,y++;
res = 1e9;
if(x==y) puts("0");
else
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res= min(res,query(1,id[top[x]],id[x],3));
x = fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
res = min(res,query(1,id[y]+1,id[x],3));
printf("%d\n",res);
}
}
}
return 0;
}

浙公网安备 33010602011771号