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;
    }
    
  • 相关阅读:
    Ubuntu安装搜狗输入法
    Ubuntu 命令
    ubuntu忽然不能登录,输入密码正确一直返回登录界面
    chmod用法
    Maven学习(六)maven使用中遇到的坑
    win10下装mysql-5.7.18-winx64
    Maven学习(五)使用Maven构建多模块项目
    Maven学习(四)eclipse创建maven项目
    Maven学习(三)maven原理概念详述
    Struts2+Hibernate4+Spring4框架整合搭建Java项目原型
  • 原文地址:https://www.cnblogs.com/ugly-CYW-lyr-ddd/p/9460594.html
Copyright © 2011-2022 走看看