​https://www.luogu.com.cn/problem/P7735​

网上的做法我找到的分两种,一种是染色法,这种做法好写,但是我不认为以我的脑子能想出来。另一种是暴力维护,因为易知与任何一点相关联的重边最多只有两条,好想不好写。

当然这里就说下前者的做法。每次操作时相当于为路径上的所有点染上一种与众不同的颜色。而至于重边的判断,则是边的端点颜色相同(且不为0)。由此树链剖分维护即可。

(这种做法是咋想到的啊……要不然就是我题刷少了QAQ)



#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
inline int read(){
int X=0,w=0;char ch=0;
while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();}
while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline int check(int l,int r){
return (l==r)&&l;
}
struct Ans{
int l,r,sum;
Ans(){
l=r=sum=0;
}
Ans(int _l,int _r,int _sum){
l=_l;r=_r;sum=_sum;
}
Ans operator +(const Ans& b)const{
int L=(!l)?b.l:l;
int R=(!b.r)?r:b.r;
return Ans(L,R,sum+b.sum+check(r,b.l));
}
};
struct node{
int to,nxt;
}e[N<<1];
struct tree{
int lazy;
Ans d;
}t[N<<2];
int head[N],cnt,tot,n,m,rt;
int fa[N],pos[N],idx[N],son[N],size[N],dep[N],top[N];
inline void add(int u,int v){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
void dfs1(int u){
size[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(fa[u]==v)continue;
fa[v]=u;dep[v]=dep[u]+1;
dfs1(v);
size[u]+=size[v];
if(!son[u]||size[son[u]]<size[v])son[u]=v;
}
}
void dfs2(int u,int anc){
pos[u]=++tot;idx[tot]=u;top[u]=anc;
if(!son[u])return;
dfs2(son[u],anc);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
inline void init(){
dep[rt]=1;
dfs1(rt);
dfs2(rt,rt);
}
void build(int a,int l,int r){
if(l==r){
t[a].lazy=0;
t[a].d=Ans();
return;
}
int mid=(l+r)>>1;
build(a<<1,l,mid);build(a<<1|1,mid+1,r);
t[a].lazy=0;
t[a].d=t[a<<1].d+t[a<<1|1].d;
}
void pushdown(int a,int l,int r){
int mid=(l+r)>>1;
if(t[a].lazy){
t[a<<1].lazy=t[a].lazy;
t[a<<1|1].lazy=t[a].lazy;
t[a<<1].d=Ans(t[a].lazy,t[a].lazy,mid-l);
t[a<<1|1].d=Ans(t[a].lazy,t[a].lazy,r-mid-1);
t[a].lazy=0;
}
return;
}
inline Ans query(int a,int l,int r,int l1,int r1){
if(r1<l||r<l1)return Ans();
if(l1<=l&&r<=r1)return t[a].d;
int mid=(l+r)>>1;pushdown(a,l,r);
Ans tmp=query(a<<1,l,mid,l1,r1)+query(a<<1|1,mid+1,r,l1,r1);
return tmp;
}
inline void modify(int a,int l,int r,int l1,int r1,int v){
if(r1<l||r<l1)return;
if(l1<=l&&r<=r1){
t[a].lazy=v;
t[a].d=Ans(v,v,r-l);
return;
}
int mid=(l+r)>>1;pushdown(a,l,r);
modify(a<<1,l,mid,l1,r1,v);modify(a<<1|1,mid+1,r,l1,r1,v);
t[a].d=t[a<<1].d+t[a<<1|1].d;
}
inline int pathquery(int x,int y){
int op=0;
Ans ansl,ansr;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);op^=1;
}
if(!op) ansl=query(1,1,n,pos[top[x]],pos[x])+ansl;
else ansr=query(1,1,n,pos[top[x]],pos[x])+ansr;
x=fa[top[x]];
}
if(dep[x]>dep[y]){
swap(x,y);op^=1;
}
Ans ans=query(1,1,n,pos[x],pos[y]);
swap(ansl.l,ansl.r);
if(op)swap(ans.l,ans.r);
ans=ansl+ans+ansr;
return ans.sum;
}
inline void pathmodify(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
modify(1,1,n,pos[top[x]],pos[x],z);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
modify(1,1,n,pos[x],pos[y],z);
}
void initforcase(){
cnt=tot=0;rt=1;
memset(head,0,sizeof(head));
memset(son,0,sizeof(son));
}
int main(){
int T=read();
while(T--){
initforcase();
n=read(),m=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
add(u,v);add(v,u);
}
init();build(1,1,n);
for(int i=1;i<=m;i++){
int op=read();
if(op==1){
int x=read(),y=read(),z=i;
pathmodify(x,y,z);
}
if(op==2){
int x=read(),y=read();
printf("%d\n",pathquery(x,y));
}
}
}

return 0;
}


+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 

+++++++++++++++++++++++++++++++++++++++++++