zoukankan      html  css  js  c++  java
  • 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
    ",getsum(1,x));
    	}
    	return 0;
    }
    
  • 相关阅读:
    PHP实现无限极分类
    html2canvas生成并下载图片
    一次线上问题引发的过程回顾和思考,以更换两台服务器结束
    Intellij IDEA启动项目报Command line is too long. Shorten command line for XXXApplication or also for
    mq 消费消息 与发送消息传参问题
    idea 创建不了 java 文件
    Java switch 中如何使用枚举?
    Collections排序
    在idea 设置 git 的用户名
    mongodb添加字段和创建自增主键
  • 原文地址:https://www.cnblogs.com/ugly-CYW-lyr-ddd/p/9460594.html
Copyright © 2011-2022 走看看