• [Luogu] P1558 色板游戏


    (Link)

    Description

    给定一个长为(n)的区间,(m)次操作,给子区间涂一种颜色,或者查询一个区间内有多少种颜色。颜色种类数(le30),初始颜色为(1)(n,mle10^5)

    Solution

    开始想的是开(30)棵线段树,或者每个区间开一个(vector)存颜色,但后来才发现其实完全没必要。注意到颜色种类数很少,所以其实可以把它压成一个状态(S),其中(S)从左往右数第(i)位是(1)表示这个区间内有(i)这种颜色。

    那么这就很好维护了。(pushdown)就直接覆盖,(pushup)就是对儿子进行或运算就好了。

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    
    int n, m, mx;
    
    struct node
    {
    	int l, r, col, tag;
    }t[400005];
    
    char ch[2];
    
    int read()
    {
    	int x = 0, fl = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    	return x * fl;
    }
    
    void push_up(int p)
    {
    	t[p].col = (t[ls(p)].col | t[rs(p)].col);
    	return;
    }
    
    void push_down(int p)
    {
    	if (!t[p].tag) return;
    	t[ls(p)].tag = t[p].tag;
    	t[rs(p)].tag = t[p].tag;
    	t[ls(p)].col = (1 << (t[p].tag - 1));
    	t[rs(p)].col = (1 << (t[p].tag - 1));
    	t[p].tag = 0;
    	return;
    }
    
    void build(int p, int l0, int r0)
    {
    	t[p].l = l0; t[p].r = r0;
    	if (l0 == r0)
    	{
    		t[p].col = 1;
    		return;
    	}
    	int mid = (t[p].l + t[p].r) >> 1;
    	build(ls(p), l0, mid);
    	build(rs(p), mid + 1, r0);
    	push_up(p);
    	return;
    }
    
    void update(int p, int l0, int r0, int d)
    {
    	if (l0 <= t[p].l && t[p].r <= r0)
    	{
    		t[p].col = (1 << (d - 1));
    		t[p].tag = d;
    		return;
    	}
    	push_down(p);
    	int mid = (t[p].l + t[p].r) >> 1;
    	if (l0 <= mid) update(ls(p), l0, r0, d);
    	if (r0 > mid) update(rs(p), l0, r0, d);
    	push_up(p);
    	return;
    }
    
    int query(int p, int l0, int r0)
    {
    	if (l0 <= t[p].l && t[p].r <= r0) return t[p].col;
    	push_down(p);
    	int mid = (t[p].l + t[p].r) >> 1, now = 0;
    	if (l0 <= mid) now = now | query(ls(p), l0, r0);
    	if (r0 > mid) now = now | query(rs(p), l0, r0);
    	return now;
    }
    
    int main()
    {
    	n = read(); mx = read(); m = read();
    	build(1, 1, n);
    	while (m -- )
    	{
    		scanf("%s", ch);
    		if (ch[0] == 'C')
    		{
    			int l0 = read(), r0 = read(), c = read();
    			if (l0 > r0) swap(l0, r0);
    			update(1, l0, r0, c);
    		}
    		else
    		{
    			int l0 = read(), r0 = read();
    			if (l0 > r0) swap(l0, r0);
    			int cnt = query(1, l0, r0), res = 0;
    			for (int i = 0; i <= mx - 1; i ++ )
    				if (cnt & (1 << i))
    					res ++ ;
    			printf("%d
    ", res);
    		}	
    	}
    	return 0;
    }
    
  • 相关阅读:
    location.replace与location.href,location.reload的区别
    JavaScript 中 this 的用法
    setTimeout 的用法
    ngRoute 和 ui.router 的使用方法和区别
    js正则匹配只能输入有效数字可加小数点
    正则表达式
    关于浮动与清除浮动
    当给一个元素的宽度设置为百分比的时候,百分比的计算值是由它的直接父级元素的宽度决定
    内联(行级)元素不能设置margin-top
    JS判断数据是否是JSON类型
  • 原文地址:https://www.cnblogs.com/andysj/p/14006233.html
Copyright © 2020-2023  润新知