zoukankan      html  css  js  c++  java
  • 【bzoj 4154】[Ipsc2015]Generating Synergy

    题目

    大概已经掌握熟练码出(kdt)的技能了

    发现距离子树根节点(x)不超过(l)的点可以用两种方式来限制,首先(dfs)序在([dfn_x,dfn_x+sum_x))中,深度自然也要满足([deep_x,deep_x+l])

    发现这变成了对一个子矩形染色同时询问单点颜色的题目

    我们直接(kdt)打标机就好了

    需要注意的一点是,仅对(kdt)中子树的根进行的修改不打标机

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||x>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int mod=1e9+7;
    const int maxn=1e5+5;
    struct E{int v,nxt;}e[maxn];
    int head[maxn],deep[maxn],sum[maxn],dfn[maxn];
    struct Point{int x[2];}p[maxn],t;
    int n,num,cnt,__,op,T,C,m;
    int x1,x2,y1,y2;
    int l[maxn],r[maxn],tag[maxn],col[maxn],mx[maxn][2],mi[maxn][2],id[maxn];
    inline void add(int x,int y) {
    	e[++num].v=y;e[num].nxt=head[x];head[x]=num;
    }
    inline int cmp(Point A,Point B) {
    	if(A.x[op]==B.x[op]) return A.x[op^1]<B.x[op^1];
    	return A.x[op]<B.x[op];
    }
    void dfs(int x) {
    	dfn[x]=++__;sum[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt) {
    		deep[e[i].v]=deep[x]+1;
    		dfs(e[i].v);
    		sum[x]+=sum[e[i].v];
    	}
    }
    inline void pushup(int k) {
    	mx[k][0]=mi[k][0]=p[id[k]].x[0];
    	mx[k][1]=mi[k][1]=p[id[k]].x[1];
    	for(re int i=0;i<2;i++) {
    		if(l[k]) mx[k][i]=max(mx[k][i],mx[l[k]][i]),
    				 mi[k][i]=min(mi[k][i],mi[l[k]][i]);
    		if(r[k]) mx[k][i]=max(mx[k][i],mx[r[k]][i]),
    				 mi[k][i]=min(mi[k][i],mi[r[k]][i]);
    	}
    }
    inline void pushdown(int k) {
    	if(tag[k]==-1) return;
    	tag[r[k]]=tag[l[k]]=tag[k];
    	col[l[k]]=col[r[k]]=tag[k];
    	tag[k]=-1;
    }
    int build(int x,int y,int o) {
    	if(x>y) return 0;
    	int mid=x+y>>1,k=++cnt;col[k]=1;
    	op=o;std::nth_element(p+x,p+mid,p+y+1,cmp);id[k]=mid;
    	l[k]=build(x,mid-1,o^1);r[k]=build(mid+1,y,o^1);
    	pushup(k);return k;
    }
    int ask(int k,int o) {
    	if(t.x[0]==p[id[k]].x[0]&&t.x[1]==p[id[k]].x[1]) 
    		return col[k];
    	pushdown(k);
    	if(t.x[o]==p[id[k]].x[o]) {
    		if(t.x[o^1]<p[id[k]].x[o^1]) return ask(l[k],o^1);
    		return ask(r[k],o^1);
    	}
    	if(t.x[o]<p[id[k]].x[o]) return ask(l[k],o^1);
    	if(t.x[o]>p[id[k]].x[o]) return ask(r[k],o^1);
    }
    inline int out(int k) {
    	return (mx[k][0]<x1||mi[k][0]>x2||mx[k][1]<y1||mi[k][1]>y2);
    }
    inline int in(int k) {
    	return (mi[k][0]>=x1&&mx[k][0]<=x2&&mi[k][1]>=y1&&mx[k][1]<=y2);
    }
    inline int chk(Point a) {
    	return (a.x[0]>=x1&&a.x[0]<=x2&&a.x[1]>=y1&&a.x[1]<=y2);
    }
    void change(int k,int c) {
    	if(!k||out(k)) return;
    	pushdown(k);
    	if(in(k)) {col[k]=c,tag[k]=c;return;}
    	if(chk(p[id[k]])) col[k]=c;
    	change(l[k],c);change(r[k],c);
    }
    int main() {
    	T=read();
    	while(T--) {
    		n=read(),C=read(),m=read();num=0;cnt=0;
    		memset(head,0,sizeof(head));
    		memset(mx,0,sizeof(mx));
    		memset(mi,0,sizeof(mi));
    		memset(tag,-1,sizeof(tag));
    		for(re int x,i=2;i<=n;i++)
    			x=read(),add(x,i);
    		deep[1]=1,dfs(1);
    		for(re int i=1;i<=n;i++)
    			p[i].x[0]=dfn[i],p[i].x[1]=deep[i];
    		build(1,n,0);int ans=0;
    		for(re int x,c,l,i=1;i<=m;i++) {
    			x=read(),l=read(),c=read();
    			if(!c) {
    				t.x[0]=dfn[x];
    				t.x[1]=deep[x];
    				ans=(ans+1ll*i*ask(1,0)%mod)%mod;
    				continue;
    			}
    			x1=dfn[x],x2=dfn[x]+sum[x]-1;
    			y1=deep[x],y2=deep[x]+l;
    			change(1,c);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    docker API 配置与使用
    docker 启动 nginx 访问不了的问题
    微信小程序
    JavaScript -- 继承与原型链
    Chrome Google 快捷键
    jquery中attr和prop的区别
    Vue购物车实例
    jquery添加html代码的几种方法
    DeepFaceLab错误:DLL Load failed 找不到指定模块!
    DeepFaceLab:手动提取高精度脸图,减少抖动!
  • 原文地址:https://www.cnblogs.com/asuldb/p/10757483.html
Copyright © 2011-2022 走看看