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;
    }
    
  • 相关阅读:
    Leetcode 290 Word Pattern
    Leetcode 205 Isomorphic Strings
    Leetcode 345 Reverse Vowels in a String
    Leetcode 151 Reverse Words in a String
    Leetcode 344 Reverse String
    Leetcode 383 Ransom Note
    leetcode 387 First Unique Character in a String
    反码补码和位运算
    SpringBoot进阶
    布隆过滤器
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5591663.html
Copyright © 2011-2022 走看看