• 树剖学习


    树剖学习

    主要分为两部分

    剖分-dfs

    树链的应用-线段树 LCA等

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define M 1001010
    using namespace std;
    //xx
    int n,m,a[1001010],r,p;
    struct note {
    	int l,r,tag,sum;
    }c[1001010];
    //tree
    int ver[M],nex[M],head[M],cnt;
    int siz[M],fa[M],dep[M],son[M];
    //ll
    int id[M],tot,cur[M],top[M];
    ///////////////add
    inline void add(int x,int y) {
    	ver[++cnt]=y;
    	nex[cnt]=head[x];
    	head[x]=cnt;
    }
    
    ///////////////main
    void dfs1(int u) {
    	siz[u]=1;
    	for (int x=head[u];x;x=nex[x] ) {
    		int v=ver[x];
    		if(v!=fa[u]) {
    			dep[v]=dep[u]+1;
    			fa[v]=u;
    			dfs1(v);
    			siz[u]+=siz[v];
    			if (siz[v]>siz[son[u]]) son[u]=v;
    		}
    	}
    }
    
    void dfs2(int u,int t) {
    	id[u]=++tot;
    	cur[tot]=a[u];
    	top[u]=t;
    	if (son[u]) dfs2(son[u],t);
    	for (int x=head[u];x;x=nex[x]) {
    		int v=ver[x];
    		if (v!=fa[u]&&v!=son[u]) dfs2(v,v);
    	}
    }
    ///////////////////xianduanshu
    inline int lson(int x) {return x<<1;}
    inline int rson(int x) {return x<<1|1;}
    inline int diss(int x) {return c[x].r-c[x].l+1;}
    inline int mid(int l,int r) {return(l+r)>>1;}
    inline void update(int x) {c[x].sum=c[lson(x)].sum+c[rson(x)].sum;}
    
    void pushdown(int x) {
    	if (c[x].tag) {
    		c[lson(x)].sum+=c[x].tag*diss(lson(x));
    		c[rson(x)].sum+=c[x].tag*diss(rson(x));
    		c[lson(x)].tag+=c[x].tag;
    		c[rson(x)].tag+=c[x].tag;
    		c[x].tag=0;
    	}
    }
    
    void build(int x,int l,int r) {
    	c[x].l=l;c[x].r=r;
    	if (l==r) {
    		c[x].sum=cur[l];
    		return;
    	}
    	build(lson(x),l,mid(l,r));
    	build(rson(x),mid(l,r)+1,r);
    	update(x);	
    }
    
    inline int query(int x,int l,int r) {
    	int ans=0;
    	if (c[x].l>=l&&c[x].r<=r) 
    		return c[x].sum;
    	pushdown(x);
    	int mi=mid(c[x].l,c[x].r);
    	if (l<=mi) ans+=query(lson(x),l,r);
    	if (r>mi) ans+=query(rson(x),l,r);
    	return ans;
    }
    
    inline void change(int x,int l,int r,int d) {
    	if (c[x].l>=l&&c[x].r<=r) {
    		c[x].sum+=diss(x)*d;
    		c[x].tag+=d;
    		return;
    	}
    	pushdown(x);
    	int mi=mid(c[x].l,c[x].r);
    	if (l<=mi) change(lson(x),l,r,d);
    	if (r>mi) change(rson(x),l,r,d);
    	update(x);
    	return;
    	
    }
    
    int calsum(int x,int y) {
    	int anss=0;
    	while (top[x]!=top[y]) {
    		if (dep[top[x]]<dep[top[y]]) swap(x,y);
    		anss+=query(1,id[top[x]],id[x]);
    		x=fa[top[x]];
    	}
    	if (dep[x]>dep[y]) swap(x,y);
    	anss+=query(1,id[x],id[y]);
    	return anss;
    }
    
    inline void calchan(int x,int y,int d) {
    	while (top[x]!=top[y]) {
    		if (dep[top[x]]<dep[top[y]]) swap(x,y);
    		change(1,id[top[x]],id[x],d);
    		x=fa[top[x]];
    	}
    	if (dep[x]>dep[y]) swap(x,y);
    	change(1,id[x],id[y],d);
    }
    
    int sonsum(int x) {
    	int ans=0;
    	ans+=query(1,id[x],id[x]+siz[x]-1);
    	return ans;
    }
    
    inline void sonchan(int x,int d) {
    	change(1,id[x],id[x]+siz[x]-1,d);
    	return;
    }
    ////////////////mainn
    int main() {
    	scanf("%d%d%d%d",&n,&m,&r,&p);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	int x,y,z;
    	for (int i=1;i<n;i++) {
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	dfs1(r);
    	dfs2(r,r);
    	build(1,1,n);
    	int sc;
    	while (m--) {
    		scanf("%d",&sc);
    		if (sc==1) {
    			scanf("%d%d%d",&x,&y,&z);
    			calchan(x,y,z);
    		}
    		if (sc==2) {
    			scanf("%d%d",&x,&y);
    			printf("%d
    ",calsum(x,y)%p);
    		}
    		if (sc==3) {
    			scanf("%d%d",&x,&z);
    			sonchan(x,z);
    		}
    		if (sc==4) {
    			scanf("%d",&x);
    			printf("%d
    ",sonsum(x)%p);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    【零基础】极星量化入门九:找到boll的最优回测参数
    【零基础】极星量化入门八:简单的boll实盘
    【零基础】极星量化入门七:简单的boll回测
    解决element-ui中el-menu组件作为vue-router模式在刷新页面后default-active属性与当前路由页面不一致问题的方法
    vue+elementui selet框组件封装 传值
    b模块 小结
    移动端最简单的适配
    判断移动机型字符串
    前端记录cookie 点赞只能点一次
    用chrome预览微信浏览器访问需要OAuth2.0网页授权的页面 适合 微信朋友圈小游戏 HTML5小游戏 微信游戏网页
  • 原文地址:https://www.cnblogs.com/still-here-shining/p/15001180.html
Copyright © 2020-2023  润新知