• [BZOJ4154/Ipsc2015]Generating Synergy


    Description
    给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色

    Input
    第一行一个数T,表示数据组数
    接下来每组数据的第一行三个数n,C,q表示结点个数,颜色数和操作数
    接下来一行n-1个数描述2..n的父节点
    接下来q行每行三个数a,l,c
    若c为0,表示询问a的颜色
    否则将距离a不超过l的a的子节点染成c

    Output
    设当前是第i个操作,(y_i)为本次询问的答案(若本次操作是一个修改则(y_i)为0),令(z_i=i*y_i),请输出(z_1+z_2+...+z_q)(10^9+7)

    Sample Input
    1
    4 3 7
    1 2 2
    3 0 0
    2 1 3
    3 0 0
    1 0 2
    2 0 0
    4 1 1
    4 0 0

    Sample Output
    32

    HINT
    第1,3,5,7的询问的答案分别为1,3,3,1,所以答案为(1*1+2*0+3*3+4*0+5*3+6*0+7*1=32).
    数据范围:
    对于100%的数据(T<leqslant6,n,m,Cleqslant10^5),
    (1leqslant aleqslant n,0leqslant lleqslant n,0leqslant cleqslant C)


    对每个点求出dfs序(L_i,R_i),和深度(d_i),然后每个点映射为平面上的((L_i,d_i))的一个点,每次修改相当于对(L_ileqslant L_xleqslant R_i,d_ileqslant d_xleqslant d_i+l)(x)染色,这个可以转化为平面上的矩阵操作

    我们建立一棵KD-Tree,支持打区间覆盖标记即可

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e5,Mod=1e9+7;
    int pre[(N<<1)+10],now[N+10],child[(N<<1)+10];
    int deep[N+10],dfn[N+10],size[N+10],pos[N+10];//pos记录i在KD-Tree中的编号
    int n,c,q,Time,tot,T;
    void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
    void insert(int x,int y){join(x,y),join(y,x);}
    void dfs(int x,int fa){
    	deep[x]=deep[fa]+1,dfn[x]=++Time,size[x]=1;
    	for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    		if (son==fa)	continue;
    		dfs(son,x);
    		size[x]+=size[son];
    	}
    }
    struct S1{
    	#define ls(x) tree[x].ls
    	#define rs(x) tree[x].rs
    	struct node{
    		int v[2],Max[2],Min[2];
    		int Lazy,val,ls,rs,ID,fa;
    		bool operator <(const node &tis)const{return v[T]<tis.v[T];}
    	}tree[N+10];
    	int root,L[2],R[2];
    	void Add(int *a,int v){a[0]=a[1]=v;}
    	int build(int l,int r,int type,int fa){
    		T=type;
    		int mid=(l+r)>>1,p=mid;
    		nth_element(tree+l,tree+mid,tree+r+1);
    		tree[p].val=1,tree[p].Lazy=0,tree[p].fa=fa;
    		tree[p].ls=tree[p].rs=0;
    		pos[tree[p].ID]=p;
    		if (l<mid)	ls(p)=build(l,mid-1,type^1,p);
    		if (r>mid)	rs(p)=build(mid+1,r,type^1,p);
    		tree[p].Min[0]=min(tree[p].v[0],min(tree[ls(p)].Min[0],tree[rs(p)].Min[0]));
    		tree[p].Min[1]=min(tree[p].v[1],min(tree[ls(p)].Min[1],tree[rs(p)].Min[1]));
    		tree[p].Max[0]=max(tree[p].v[0],max(tree[ls(p)].Max[0],tree[rs(p)].Max[0]));
    		tree[p].Max[1]=max(tree[p].v[1],max(tree[ls(p)].Max[1],tree[rs(p)].Max[1]));
    		return p;
    	}
    	void init(){
    		Add(tree[0].Max,-inf),Add(tree[0].Min,inf);
    		for (int i=1;i<=n;i++)	tree[i].v[0]=dfn[i],tree[i].v[1]=deep[i],tree[i].ID=i;
    		root=build(1,n,0,0);
    	}
    	void Add_tag(int p,int v){
    		tree[p].val=v;
    		tree[p].Lazy=v;
    	}
    	void pushdown(int p){
    		if (!tree[p].Lazy)	return;
    		Add_tag(ls(p),tree[p].Lazy);
    		Add_tag(rs(p),tree[p].Lazy);
    		tree[p].Lazy=0;
    	}
    	void Modify(int p,int v){
    		bool flag=1;
    		for (int i=0;i<2;i++)	if (R[i]<tree[p].Min[i]||L[i]>tree[p].Max[i])	return;
    		for (int i=0;i<2;i++){
    			if (L[i]>tree[p].Min[i]||R[i]<tree[p].Max[i]){
    				flag=0;
    				break;
    			}
    		}
    		if (flag){
    			Add_tag(p,v);
    			return;
    		}flag=1;
    		pushdown(p);
    		for (int i=0;i<2;i++){
    			if (tree[p].v[i]<L[i]||R[i]<tree[p].v[i]){
    				flag=0;
    				break;
    			}
    		}
    		if (flag)	tree[p].val=v;
    		Modify(ls(p),v);
    		Modify(rs(p),v);
    	}
    	void Modify(int l1,int r1,int l2,int r2,int v){
    		L[0]=l1,L[1]=l2,R[0]=r1,R[1]=r2;
    		Modify(root,v);
    	}
    	int Query(int p){//找到其到root的链,一路pushdown即可
    		static int stack[N+10]; int top=0,x=p;
    		stack[++top]=p;
    		while (tree[p].fa)	stack[++top]=tree[p].fa,p=tree[p].fa;
    		for (int i=top;i;i--)	pushdown(stack[i]);
    		return tree[x].val;
    	}
    	#undef ls
    	#undef rs
    }KDT;//KD-Tree
    int main(){
    	for (int T=read();T;T--){
    		n=read(),c=read(),q=read();
    		int res=0; Time=0,tot=0;
    		memset(now,0,sizeof(now));
    		for (int i=2;i<=n;i++)	insert(read(),i);
    		dfs(1,0),KDT.init();
    		for (int i=1;i<=q;i++){
    			int a=read(),l=read(),c=read();
    			if (c)	KDT.Modify(dfn[a],dfn[a]+size[a]-1,deep[a],deep[a]+l,c);
    			else	res=(1ll*i*KDT.Query(pos[a])+res)%Mod;
    		}
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    
  • 相关阅读:
    vue+elementUI实现权限的部门管理
    vue+elementUI实现权限的部门管理
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    20 种最奇怪的编程语言
    WinForm导出文件
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10269082.html
Copyright © 2020-2023  润新知