标签:
题意:给一个树,三种操作,一个是将第I条边的权值改变,一个是将u到v的所有边的权值取反,一个是询问u到v的路径中边的最大值
思路:和模版的树链剖分没什么区别,这题唯一的坑点就是线段树的懒惰标记,只要有更新操作或者查询操作就都要pushdown(),然后改权值的比较简单,单点更新,而区间取反我们可以用两个数组直接模拟,一个最大值的,一个区间最小值的,然后一旦取反了,就将最大值改为负的最小值,而最小值一样改为负的最大值就可以了
#include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int inf=0x3f3f3f3f; const ll INF=0x3f3f3f3f3f3f3f3fll; const int maxn=100010; int fa[maxn],siz[maxn],son[maxn],w[maxn],p[maxn],dep[maxn],fp[maxn],head[maxn]; //fa为父节点,siz为子节点中siz最大的,dep为深度,son为重儿子,w表示在线段树中的位置 int min1[maxn<<2],lazy[maxn<<2],max1[maxn<<2]; int tree_id,n,kkk=0; struct node{ int to,next; }EE[maxn*10]; void add_edge(int u,int v){ EE[kkk].to=v;EE[kkk].next=head[u];head[u]=kkk++; } void dfs1(int u,int ff,int deep){ son[u]=0;fa[u]=ff;siz[u]=1;dep[u]=deep; for(int i=head[u];i!=-1;i=EE[i].next){ int v=EE[i].to; if(v==ff) continue; dfs1(v,u,deep+1); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } void dfs2(int u,int ff){ w[u]=++tree_id;p[u]=ff; if(son[u]) dfs2(son[u],ff); else return ; for(int i=head[u];i!=-1;i=EE[i].next){ int v=EE[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } void pushup(int node){ max1[node]=max(max1[node<<1],max1[node<<1|1]); min1[node]=min(min1[node<<1],min1[node<<1|1]); } void pushdown(int node){ if(lazy[node]){ lazy[node<<1]^=1; lazy[node<<1|1]^=1; int tmp=max1[node<<1];max1[node<<1]=-min1[node<<1];min1[node<<1]=-tmp; tmp=max1[node<<1|1];max1[node<<1|1]=-min1[node<<1|1];min1[node<<1|1]=-tmp; lazy[node]=0; } } void update(int pos,int val,int le,int ri,int node){ if(le==ri){ max1[node]=min1[node]=val; lazy[node]=0; return ; } pushdown(node); int t=(le+ri)>>1; if(pos<=t) update(pos,val,le,t,node<<1); else update(pos,val,t+1,ri,node<<1|1); pushup(node); } void update1(int l,int r,int le,int ri,int node){ if(l<=le&&ri<=r){ lazy[node]^=1; int tmp=max1[node];max1[node]=-min1[node];min1[node]=-tmp; return ; } pushdown(node); int t=(le+ri)>>1; if(l<=t) update1(l,r,le,t,node<<1); if(r>t) update1(l,r,t+1,ri,node<<1|1); pushup(node); } int query(int l,int r,int le,int ri,int node){ if(l<=le&&ri<=r) return max1[node]; pushdown(node); int t=(le+ri)>>1,ans=-inf; if(l<=t) ans=max(ans,query(l,r,le,t,node<<1)); if(r>t) ans=max(ans,query(l,r,t+1,ri,node<<1|1)); return ans; } int getmax(int u,int v){ int f1=p[u],f2=p[v],tmp=-inf; while(f1!=f2){ if(dep[f1]<dep[f2]){ swap(f1,f2); swap(u,v); } tmp=max(tmp,query(w[f1],w[u],1,n,1)); u=fa[f1];f1=p[u]; } if(u==v) return tmp; if(dep[u]>dep[v]) swap(u,v); return max(tmp,query(w[son[u]],w[v],1,n,1)); } void getupdate(int u,int v){ int f1=p[u],f2=p[v]; while(f1!=f2){ if(dep[f1]<dep[f2]){ swap(f1,f2); swap(u,v); } update1(w[f1],w[u],1,n,1); u=fa[f1];f1=p[u]; } if(u==v) return ; if(dep[u]>dep[v]) swap(u,v); update1(w[son[u]],w[v],1,n,1); } int U[maxn],V[maxn],C[maxn]; int main(){ int u,v,q,s,T; char str[10]; scanf("%d",&T); while(T--){ scanf("%d",&n); memset(head,-1,sizeof(head)); memset(son,0,sizeof(son));tree_id=0;kkk=0; for(int i=0;i<n-1;i++){ scanf("%d%d%d",&U[i],&V[i],&C[i]); add_edge(U[i],V[i]);add_edge(V[i],U[i]); } dfs1(1,1,0); dfs2(1,1); memset(max1,0,sizeof(max1)); memset(min1,0,sizeof(min1)); memset(lazy,0,sizeof(lazy)); for(int i=0;i<n-1;i++){ if(dep[U[i]]>dep[V[i]]) swap(U[i],V[i]); update(w[V[i]],C[i],1,n,1); } while(1){ scanf("%s",&str); if(str[0]=='D') break; if(str[0]=='C'){ scanf("%d%d",&u,&v); update(w[V[u-1]],v,1,n,1); }else if(str[0]=='Q'){ scanf("%d%d",&u,&v); printf("%d\n",getmax(u,v)); }else if(str[0]=='N'){ scanf("%d%d",&u,&v); getupdate(u,v); } } } return 0; }
标签:
原文地址:http://blog.csdn.net/dan__ge/article/details/51881694