zoukankan      html  css  js  c++  java
  • 可爱的树链剖分(染色)

    可爱的树链剖分(染色)

    这道题 就是 一道 普通的! 树链剖分+线段树覆盖

    注意一下两个线段树合并的时候 如果 (lval(node<<1|1)==rval(node<<1)) 相当于这两个线段树的相邻的数字数相同的 那么合并时的(tot) (sum) 应该 --

    所以说这道题有什么细节吗 我感觉是没有的 然而我调了一下午+晚上两个小时 (再次感谢人帅心善的kma小哥哥) (话说为什么他有这么多女朋友,而我还是单身呢) 不 我有萌德

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    const int maxn=1e6+10;
    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*10+ch-'0';ch=getchar();};
    	return x*f;
    }
    int n,m,color[maxn],fir[maxn<<1],nxt[maxn<<1],to[maxn<<1],tot,top[maxn];
    int size[maxn],son[maxn],fa[maxn],rk[maxn],id[maxn],dep[maxn],times;
    char op[3];
    struct nodee{
    	int l,r,lval,rval,sum,tag;
    	#define lval(x) tree[x].lval
    	#define rval(x) tree[x].rval
    	#define l(x) tree[x].l
    	#define r(x) tree[x].r
    	#define sum(x) tree[x].sum
    	#define tag(x) tree[x].tag
    }tree[maxn<<4];
    void add(int x,int y){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;}
    void dfs1(int x){
    	dep[x]=dep[fa[x]]+1;size[x]=1;
    	for(int i=fir[x];i;i=nxt[i]){
    		int y=to[i];if(y==fa[x]) continue;
    		fa[y]=x;dfs1(y);size[x]+=size[y];
    		if(size[son[x]]<size[y]) son[x]=y;
    	}
    }
    void dfs2(int x,int tp){
    	top[x]=tp;id[x]=++times;rk[times]=x;
    	if(son[x]) dfs2(son[x],tp);
    	for(int i=fir[x];i;i=nxt[i]){
    		int y=to[i];if(id[y]) continue;
    		dfs2(y,y);
    	}
    }
    void push_up(int node){
    	lval(node)=lval(node<<1);rval(node)=rval(node<<1|1);
    	sum(node)=sum(node<<1)+sum(node<<1|1);
    	if(rval(node<<1)==lval(node<<1|1))	--sum(node);
    }
    void build(int node,int l,int r){
    	l(node)=l;r(node)=r;
    	if(l==r){
    		lval(node)=rval(node)=color[rk[l]];
    		sum(node)=1;return ;
    	}
    	int mid=l+r>>1;
    	build(node<<1,l,mid);build(node<<1|1,mid+1,r);
    	push_up(node);
    }
    void push_down(int node){
    	if(tag(node)){
    		tag(node<<1)=tag(node<<1|1)=tag(node);
    		lval(node<<1)=rval(node<<1)=lval(node<<1|1)=rval(node<<1|1)=tag(node);
    		sum(node<<1)=sum(node<<1|1)=1;
    		tag(node)=0;
    	}
    }
    void modify(int node,int ql,int qr,int z){
    	if(ql<=l(node) && r(node)<=qr){
    		sum(node)=1;tag(node)=z;
    		lval(node)=z;rval(node)=z;
    		return ;
    	}
    	push_down(node);
    	int mid=l(node)+r(node)>>1;
    	if(ql<=mid)	modify(node<<1,ql,qr,z);
    	if(mid<qr) modify(node<<1|1,ql,qr,z);
    	push_up(node);
    }
    void chain_modify(int x,int y,int z){
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]]){
    			x^=y^=x^=y;
    		}
    		modify(1,id[top[x]],id[x],z);
    		x=fa[top[x]];
    	}
    	if(dep[x]<dep[y])	x^=y^=x^=y;
    	modify(1,id[y],id[x],z);
    	return ;
    }
    int Rval = 0,Lval = 0,last1 = 0,last2 = 0;
    int query(int node,int ql,int qr){
    	if(ql==l(node))	Lval=lval(node);
    	if(qr==r(node))	Rval=rval(node);
    	if(ql<=l(node) && r(node)<=qr){
    		return sum(node);
    	}
    	push_down(node);
    	int ans=0,mid=l(node)+r(node)>>1;
    	if(ql>mid) ans+=query(node<<1|1,ql,qr);
    	else if (qr <= mid) ans += query(node<<1,ql,qr);
    	else {
    			if(rval(node<<1)==lval(node<<1|1))	ans+=query(node<<1,ql,qr)+query(node<<1|1,ql,qr)-1;
    		else ans+=query(node<<1,ql,qr)+query(node<<1|1,ql,qr);
    	}
    	return ans;
    }
    int chain_query(int x,int y){
    	last1 = 0, last2 = 0, Lval = 0, Rval = 0;
    	int tx=top[x],ty=top[y];
    	int ans=0;
    	while(tx!=ty){
    		if(dep[tx]<dep[ty]){
    			x^=y^=x^=y;
    			tx^=ty^=tx^=ty;
    			last1^=last2^=last1^=last2;
    		}
    		ans+=query(1,id[tx],id[x]);
    		if(last1==Rval)	--ans;
    		last1=Lval;
    		x=fa[tx];tx=top[x];
    	}
    	if(dep[x]<dep[y]){
    		x^=y^=x^=y;
    		last1^=last2^=last1^=last2;
    	}
    	ans+=query(1,id[y],id[x]);
    	if(Rval==last1) ans--;
    	if(Lval==last2) ans--;
    	return ans;
    }
    signed main(){
    	n=read();m=read();
    	for(int i=1;i<=n;i++)
    		color[i]=read();
    	for(int i=1,x,y;i<=n-1;i++){
    		x=read();y=read();
    		add(x,y);add(y,x);
    	}
    	dfs1(1);dfs2(1,1);
    	build(1,1,n);
    	for(int i=1,x,y,z;i<=m;i++){
    		scanf("%s",op + 1);x=read();y=read();
    		if(op[1]=='C') {
    			z=read();chain_modify(x,y,z);
    		}
    		if(op[1]=='Q') printf("%lld
    ",chain_query(x,y));
    	}
    	return 0;
    }
    

    但是注意一下 在chain_query 和 chain_modify 的时候 最后的判断语句一定不能改方向(为什么呢我不知道) 我好难受啊

  • 相关阅读:
    maven超级pom内容
    elasticsearch日志删除命令
    maven 设置跳过测试
    centos7.4 开启ftp服务
    部分Linux时区改为东八区的方法
    docker overlay存储驱动介绍(传送门)
    HotSpot学习(一)——如何下载openjdk源码
    nginx 代理静态资源报 403
    【转载】C#通过遍历DataTable的列获取所有列名
    【转载】C#通过Remove方法移除DataTable中的某一列数据
  • 原文地址:https://www.cnblogs.com/mendessy/p/11755588.html
Copyright © 2011-2022 走看看