zoukankan      html  css  js  c++  java
  • 洛谷 [P2486] 染色

    树剖+线段树维护连续相同区间个数

    注意什么时候长度要减一

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define ll long long
    using namespace std;
    const int MAXN=100005;
    int top[MAXN],head[MAXN],nume,n,m,dep[MAXN],fa[MAXN],son[MAXN],siz[MAXN],id[MAXN],wei[MAXN],wein[MAXN],ind;
    struct edge{
    	int to,nxt;
    }e[MAXN<<1];
    int init(){
    	int rv=0,fh=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') fh=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		rv=(rv<<1)+(rv<<3)+c-'0';
    		c=getchar();
    	}
    	return fh*rv;
    }
    void adde(int from,int to){
    	e[++nume].to=to;
    	e[nume].nxt=head[from];
    	head[from]=nume;
    }
    void dfs1(int u,int rt){
    	dep[u]=dep[rt]+1;
    	fa[u]=rt;
    	siz[u]=1;
    	int ma=0;
    	for(int i=head[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==rt) continue;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		if(siz[v]>ma){
    			ma=siz[v];
    			son[u]=v;
    		}
    	}
    }
    void dfs2(int u,int topf){
    	top[u]=topf;
    	id[u]=++ind;
    	wein[ind]=wei[u];
    	if(!son[u]) return;
    	dfs2(son[u],topf);
    	for(int i=head[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa[u]||v==son[u]) continue;
    		dfs2(v,v);
    	}
    }
    struct SGT{
    	int sum[MAXN<<2],tag[MAXN<<2],lc[MAXN<<2],rc[MAXN<<2];
    	void PushUp(int rt){
    		sum[rt]=sum[rt<<1]+sum[rt<<1|1]-(rc[rt<<1]==lc[rt<<1|1]);
    		lc[rt]=lc[rt<<1];rc[rt]=rc[rt<<1|1];
    	}
    	void build(int l,int r,int rt){
    		if(l==r){
    			sum[rt]=1;
    			lc[rt]=rc[rt]=wein[l];
    			return ;
    		}
    		int mid=(l+r)>>1;
    		build(lson);
    		build(rson);
    		PushUp(rt);
    	}
    	void PushDown(int rt){
    		if(tag[rt]){
    			tag[rt<<1]=tag[rt<<1|1]=tag[rt];
    			sum[rt<<1]=sum[rt<<1|1]=1;
    			lc[rt<<1]=rc[rt<<1]=lc[rt<<1|1]=rc[rt<<1|1]=tag[rt];
    			tag[rt]=0;
    		}
    	}
    	void Update(int L,int R,int add,int l,int r,int rt){
    		if(L<=l&&r<=R){
    			sum[rt]=1;
    			lc[rt]=rc[rt]=add;
    			tag[rt]=add;
    			return;
    		}
    		PushDown(rt);
    		int mid=(l+r)>>1;
    		if(L<=mid) Update(L,R,add,lson);
    		if(mid<R) Update(L,R,add,rson);
    		PushUp(rt);
    	}
    	int Query(int L,int R,int l,int r,int rt){
    		if(L<=l&&r<=R){
    			return sum[rt];
    		}
    		PushDown(rt);
    		int mid=(l+r)>>1;
    		int ans=0,f=0;
    		if(L<=mid) ans+=Query(L,R,lson),f++;
    		if(mid<R) ans+=Query(L,R,rson),f++;
    		if(f==2){
    			ans-=(rc[rt<<1]==lc[rt<<1|1]);
    		}
    		PushUp(rt);
    		return ans;
    	}
    	int find(int loc,int l,int r,int rt){
    		if(l==r){
    			return rc[rt];
    		}
    		PushDown(rt);
    		int mid=(l+r)>>1;
    		int ans=0;
    		if(loc<=mid) ans=find(loc,lson);
    		else ans=find(loc,rson);
    		PushUp(rt);
    		return ans;
    	}
    }sgt;
    void UpdateRange(int u,int v,int add){
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]]) swap(u,v);
    		sgt.Update(id[top[u]],id[u],add,1,n,1);
    		u=fa[top[u]];
    	}
    	if(dep[u]>dep[v]) swap(u,v);
    	sgt.Update(id[u],id[v],add,1,n,1);
    }
    int QueryRange(int u,int v){
    	int ans=0;
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]]) swap(u,v);
    		ans+=sgt.Query(id[top[u]],id[u],1,n,1);
    		ans-=(sgt.find(id[fa[top[u]]],1,n,1)==sgt.find(id[top[u]],1,n,1));
    		u=fa[top[u]];
    	}
    	if(dep[u]>dep[v]) swap(u,v);
    	ans+=sgt.Query(id[u],id[v],1,n,1);
    	return ans;
    }
    int main(){
    	n=init();m=init();
    	for(int i=1;i<=n;i++) wei[i]=init();
    	for(int i=1;i<n;i++){
    		int u=init(),v=init();
    		adde(u,v);adde(v,u);
    	}
    	dep[1]=1;
    	dfs1(1,0);
    	dfs2(1,1);
    	sgt.build(1,n,1);
    	char s[10];
    	/*for(int i=1;i<=n;i++) printf("%d ",wein[id[i]]);
    	cout<<endl;
    	for(int i=1;i<=n;i++) printf("%d ",sgt.find(id[i],1,n,1));
    	cout<<endl;*/
    	for(int i=1;i<=m;i++){
    		scanf("%s",s);
    		if(s[0]=='C'){
    			int a=init(),b=init(),t=init();
    			UpdateRange(a,b,t);
    			/*for(int i=1;i<=n;i++) printf("%d ",sgt.find(id[i],1,n,1));
    			cout<<endl;*/
    		}else {
    			int a=init(),b=init();
    			printf("%d
    ",QueryRange(a,b));
    		}
    	}
    	for(int i=1;i<=n;i++) ;
    	return 0;
    }
    
  • 相关阅读:
    poj 1789 每个字符串不同的字母数代表两个结点间的权值 (MST)
    poj 1251 poj 1258 hdu 1863 poj 1287 poj 2421 hdu 1233 最小生成树模板题
    poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)
    hdu 5256 最少修改多少个数 能使原数列严格递增 (LIS)
    hdu 1025 上面n个点与下面n个点对应连线 求最多能连有多少条不相交的线 (LIS)
    Gym 100512F Funny Game (博弈+数论)
    UVa 12714 Two Points Revisited (水题,计算几何)
    UVa 12717 Fiasco (BFS模拟)
    UVa 12718 Dromicpalin Substrings (暴力)
    UVa 12716 && UVaLive 6657 GCD XOR (数论)
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8410431.html
Copyright © 2011-2022 走看看