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;
}

猜你喜欢

转载自www.cnblogs.com/ugly-CYW-lyr-ddd/p/9460594.html