BZOJ1103
BZOJ1103
题意
给定一棵树,根为1,要求支持两个操作
\(1、将点u到点v的路径上的边权置为0\)
\(2、查询点1到点u的路径边权和\)
做法
这显然是个差分/线段树/树状数组的题,但是不喜欢拿辅助数组维护\(bit\)的题主还是想写线段树,于是就用的树剖套线段树
代码
#include<bits/stdc++.h>
#define lc root<<1
#define rc root<<1|1
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define rg register
using namespace std;
const int maxn=250010;
struct Edge{int v,next;}edge[maxn<<1];
int head[maxn],father[maxn],deep[maxn],size[maxn],son[maxn],num[maxn],top[maxn],line[maxn],dis[maxn];
int lazy[maxn<<2],sum[maxn<<2];
int n,cnt=0,tot=0;
inline void addEdge(int u,int v){edge[++cnt]=(Edge){v,head[u]};head[u]=cnt;}
inline void dfs(int u,int fa){
size[u]=1;
for (rg int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
if (v==fa) continue;
father[v]=u;deep[v]=deep[u]+1;
dfs(v,u);
size[u]+=size[v];
if (size[v]>size[son[u]]) son[u]=v;
}
}
inline void dfs2(int u,int t){
top[u]=t;num[u]=++tot;line[tot]=u;
if (!son[u]) return;
dfs2(son[u],t);
for (rg int i=head[u];i;i=edge[i].next)
if (edge[i].v!=father[u] && edge[i].v!=son[u]) dfs2(edge[i].v,edge[i].v);
}
inline int read(){int x=0,f=1;char ch=getchar();while (ch<'0' || ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}return x*f;}
inline void pushdown(int root,int l,int r){
if (!lazy[root]) return;
lazy[lc]=lazy[rc]=1;
int mid=l+r>>1;
sum[lc]=sum[rc]=lazy[root]=0;
}
inline void pushup(int root){sum[root]=sum[lc]+sum[rc];}
inline void build(int l,int r,int root){
lazy[root]=0;
if (l==r) {sum[root]=dis[line[l]];return;}
int mid=l+r>>1;
build(lson);build(rson);
pushup(root);
}
inline void update(int L,int R,int l,int r,int root){
if (l>=L && r<=R){
sum[root]=0;
lazy[root]=1;
return;
}
pushdown(root,l,r);
int mid=l+r>>1;
if (L<=mid) update(L,R,lson);
if (mid<R) update(L,R,rson);
pushup(root);
}
inline int query(int L,int R,int l,int r,int root){
if (l>=L && r<=R) return sum[root];
pushdown(root,l,r);
int mid=l+r>>1,ans=0;
if (L<=mid) ans+=query(L,R,lson);
if (R>mid) ans+=query(L,R,rson);
return ans;
}
inline void change(int u,int v){
while (top[u]!=top[v]){
if (deep[top[u]]<deep[top[v]]) swap(u,v);
update(num[top[u]],num[u],1,n,1);
u=father[top[u]];
}
if (deep[u]>deep[v]) swap(u,v);
update(num[u]+1,num[v],1,n,1);
}
inline int getsum(int u,int v){
int ans=0;
while (top[u]!=top[v]){
if (deep[top[u]]<deep[top[v]]) swap(u,v);
ans+=query(num[top[u]],num[u],1,n,1);
u=father[top[u]];
}
if (u==v) return ans;
if (deep[u]>deep[v]) swap(u,v);
ans+=query(num[u]+1,num[v],1,n,1);
return ans;
}
int main(){
n=read();
for (rg int i=1;i<n;i++) {
int u=read(),v=read();
addEdge(u,v);addEdge(v,u);
if (u>v) dis[u]++;else dis[v]++;
}
dfs(1,0);dfs2(1,1);
build(1,n,1);
int q=read()+n-1;
while (q--){
char ch=getchar();int x=read(),y;
if (ch=='A') y=read(),change(x,y);
else printf("%d\n",getsum(1,x));
}
return 0;
}