zoukankan      html  css  js  c++  java
  • [BZOJ4154][Ipsc2015]Generating Synergy

    [BZOJ4154][Ipsc2015]Generating Synergy

    试题描述

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

    输入

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

    输出

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

    输入示例

    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

    输出示例

    32

    数据规模及约定

    对于100%的数据T<=6,n,m,c<=10^5,
    1<=a<=n,0<=l<=n,0<=c<=c

    题解

    一开始看错题了。。。后来才发现只染子树中的点。

    那么就可以以每个节点的 DFS 序作为横坐标,深度作为纵坐标,那么就可以把一棵树放在坐标系里了,一次 a 节点,距离为 l 的染色就是纵坐标从 dep[a] 到 dep[a] + l,横坐标从 dfsx[a] 到 dfsx[a] + siz[a] - 1 的矩形,其中 dep[a] 表示节点 a 的深度,dfsx[a] 指节点 a 的 DFS 序,siz[a] 表示以节点 a 为根的子树大小。需要标记下传。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
    
    #define maxn 100010
    #define maxm 200010
    #define oo 2147483647
    #define MOD 1000000007
    #define LL long long
    int n, m, fa[maxn], dep[maxn], head[maxn], next[maxm], to[maxm], dl[maxn], dr[maxn];
    
    void AddEdge(int a, int b) {
    	to[++m] = b; next[m] = head[a]; head[a] = m;
    	swap(a, b);
    	to[++m] = b; next[m] = head[a]; head[a] = m;
    	return ;
    }
    int clo;
    void build(int u, int d) {
    	dl[u] = ++clo; dep[u] = d;
    	for(int e = head[u]; e; e = next[e]) if(to[e] != fa[u]) build(to[e], d + 1);
    	dr[u] = clo;
    	return ;
    }
    
    int root, lc[maxn], rc[maxn];
    bool Cur;
    struct Node {
    	int x[2], mx[2], mn[2], col, setv;
    	bool operator < (const Node& t) const { return x[Cur] < t.x[Cur]; }
    	bool operator == (const Node& t) const { return x[0] == t.x[0] && x[1] == t.x[1]; }
    } ns[maxn];
    void maintain(int o) {
    	int l = lc[o], r = rc[o];
    	for(int i = 0; i < 2; i++) {
    		ns[o].mx[i] = max(max(ns[l].mx[i], ns[r].mx[i]), ns[o].x[i]);
    		ns[o].mn[i] = min(min(ns[l].mn[i], ns[r].mn[i]), ns[o].x[i]);
    	}
    	return ;
    }
    void build(int& o, int L, int R, bool cur) {
    	if(L > R){ o = 0; return ; }
    	int M = L + R >> 1; o = M;
    	Cur = cur; nth_element(ns + L, ns + M, ns + R + 1);
    	build(lc[o], L, M - 1, cur ^ 1); build(rc[o], M + 1, R, cur ^ 1);
    	maintain(o);
    	return ;
    }
    Node x, y;
    void pushdown(int o) {
    	if(!ns[o].setv) return ;
    	ns[o].col = ns[lc[o]].setv = ns[rc[o]].setv = ns[o].setv; ns[o].setv = 0;
    	return ;
    }
    bool all(int o) { return x.x[0] <= ns[o].mn[0] && ns[o].mx[0] <= y.x[0] && x.x[1] <= ns[o].mn[1] && ns[o].mx[1] <= y.x[1]; }
    bool has(int o) { return !(ns[o].mx[0] < x.x[0] || ns[o].mn[0] > y.x[0] || ns[o].mx[1] < x.x[1] || ns[o].mn[1] > y.x[1]); }
    void update(int o, int c) {
    	if(!o) return ;
    	pushdown(o);
    	int xx = ns[o].x[0], yy = ns[o].x[1];
    	if(x.x[0] <= xx && xx <= y.x[0] && x.x[1] <= yy && yy <= y.x[1]) ns[o].col = c;
    	if(all(lc[o])) ns[lc[o]].setv = c;
    	else if(has(lc[o])) update(lc[o], c);
    	if(all(rc[o])) ns[rc[o]].setv = c;
    	else if(has(rc[o])) update(rc[o], c);
    	return ;
    }
    int query(int o) {
    	if(!o) return -1;
    	pushdown(o);
    	if(x == ns[o]) return ns[o].col;
    	int tmp = -1;
    	if(ns[lc[o]].mn[0] <= x.x[0] && x.x[0] <= ns[lc[o]].mx[0] && ns[lc[o]].mn[1] <= x.x[1] && x.x[1] <= ns[lc[o]].mx[1])
    		tmp = query(lc[o]);
    	if(tmp < 0) tmp = query(rc[o]);
    	return tmp;
    }
    
    int main() {
    	ns[0].mx[0] = ns[0].mx[1] = -oo;
    	ns[0].mn[0] = ns[0].mn[1] = oo;
    	int T = read();
    	while(T--) {
    		m = 0; memset(head, 0, sizeof(head));
    		n = read(); int c = read(), q = read();
    		for(int i = 2; i <= n; i++) AddEdge(fa[i] = read(), i);
    		clo = 0; build(1, 1);
    		for(int i = 1; i <= n; i++) ns[i].x[0] = dl[i], ns[i].x[1] = dep[i], ns[i].col = 1, ns[i].setv = 0;
    		build(root, 1, n, 0);
    		LL ans = 0;
    		for(int i = 1; i <= q; i++) {
    			int a = read(), l = read(), c = read(), tmp = 0;
    			if(c) {
    				x.x[0] = dl[a]; y.x[0] = dr[a]; x.x[1] = dep[a]; y.x[1] = dep[a] + l;
    				update(root, c);
    			}
    			else {
    				x.x[0] = dl[a]; x.x[1] = dep[a];
    				tmp = query(root);
    			}
    			ans += (LL)tmp * i;
    			if(ans >= MOD) ans %= MOD;
    		}
    		printf("%lld
    ", ans);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    heat模板
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode819.Most Common Word最常见的单词
    Leetcode819.Most Common Word最常见的单词
    Leetcode783.Minimum Distance Between BST Nodes二叉搜索树结点最小距离
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5591663.html
Copyright © 2011-2022 走看看