• P1558 色板游戏


    P1558 色板游戏

    题目背景
    阿宝上学了,今天老师拿来了一块很长的涂色板。

    题目描述
    色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, ... L。

    现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:

    "C A B C" 指在A到 B 号方格中涂上颜色 C。
    "P A B" 指老师的提问:A到 B号方格中有几种颜色。
    学校的颜料盒中一共有 T 种颜料。为简便起见,我们把他们标记为 1, 2, ... T. 开始时色板上原有的颜色就为1号色。 面对如此复杂的问题,阿宝向你求助,你能帮助他吗?

    输入输出格式
    输入格式:
    第一行有3个整数 L (1 <= L <= 100000), T (1 <= T <= 30) 和 O (1 <= O <= 100000)。 在这里O表示事件数。
    接下来 O 行, 每行以 "C A B C" 或 "P A B" 得形式表示所要做的事情(这里 A, B, C 为整数, 可能A> B,这样的话需要你交换A和B)

    输出格式:
    对于老师的提问,做出相应的回答。每行一个整数。


    错误日志: 1.第一次交了暴力 (30) 颗线段树 (MLE) 2. 后面换了个思路却忘记了题目有坑(以粗体标出)


    Solution

    这里要说一下 (bitset) 这个宝贝了(快 (noip) 了, 多运用 (STL) 节省时间)
    支持位数很大的二进制运算, 自带压缩, 运算较快
    简单来说就是一个可以有很多位的状压利器

    这题很明显线段树, 用了 (bitset) 做状态说明: 第 (i) 位 为 (1) 代表此区间有这个颜色, 为 (0) 则没有
    上传更新时使用或运算, 表示取并集(bitset很大一用处就是取状态很多的并集, 十分方便)
    这是满足分配律的

    修改打懒标记记录区间颜色, 改区间状态直接把 (bitset) 赋值为 (0) 然后确定颜色位修改为 (1) 即可

    附: (bitset) 用法

    声明n位bitset : bitset<n> b;
    全部赋值为0 : b.reset();
    为1 : b.set();
    对第i位操作 : b[i] = 1/0;
    一个bitset里1的个数 : num = b.count();
    

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<bitset>
    typedef long long LL;
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 100019;
    int num, numc, na;
    #define lid (id << 1)
    #define rid (id << 1) | 1
    struct seg_tree{
    	int l, r;
    	int lazy;
    	bitset<39>b;
    	}tree[maxn << 2];
    void pushup(int id){
    	tree[id].b = tree[lid].b | tree[rid].b;
    	}
    void pushdown(int id){
    	if(tree[id].lazy){
    		int c = tree[id].lazy;
    		tree[lid].b.reset(), tree[rid].b.reset();
    		tree[lid].b[c] = 1, tree[rid].b[c] = 1;
    		tree[lid].lazy = tree[rid].lazy = c;
    		tree[id].lazy = 0;
    		}
    	}
    void build(int id, int l, int r){
    	tree[id].l = l, tree[id].r = r;
    	if(l == r){
    		tree[id].b[1] = 1;
    		return ;
    		}
    	int mid = (l + r) >> 1;
    	build(lid, l, mid), build(rid, mid + 1, r);
    	pushup(id);
    	}
    void update(int id, int val, int l, int r){
    	pushdown(id);
    	if(tree[id].l == l && tree[id].r == r){
    		tree[id].b.reset();
    		tree[id].b[val] = 1;
    		tree[id].lazy = val;
    		return ;
    		}
    	int mid = (tree[id].l + tree[id].r) >> 1;
    	if(mid < l)update(rid, val, l, r);
    	else if(mid >= r)update(lid, val, l, r);
    	else update(lid, val, l, mid), update(rid, val, mid + 1, r);
    	pushup(id);
    	}
    bitset<39> query(int id, int l, int r){
    	pushdown(id);
    	if(tree[id].l == l && tree[id].r == r){
    		return tree[id].b;
    		}
    	int mid = (tree[id].l + tree[id].r) >> 1;
    	if(mid < l)return query(rid, l, r);
    	else if(mid >= r)return query(lid, l, r);
    	else return query(lid, l, mid) | query(rid, mid + 1, r);
    	}
    int main(){
    	num = RD();numc = RD();na = RD();
    	build(1, 1, num);
    	char cmd;
    	for(int i = 1;i <= na;i++){
    		cin>>cmd;
    		int l = RD(), r = RD();
    		if(l > r)swap(l, r);
    		if(cmd == 'C'){
    			int x = RD();
    			update(1, x, l, r);
    			}
    		else printf("%d
    ", (int)query(1, l, r).count());
    		}
    	return 0;
    	}
    
  • 相关阅读:
    CSDN的验证码,真得很糟糕
    CSDN的验证码,为什么要这样呢
    <转>http协议 文件下载原理详解
    验证码,验证码,继续
    搞了一天,气死我了
    昨天下午三点,到晚上六点写的(干死单文档)
    一个早晨加,一个上午的结果
    Linux+QT4+我忙活半宿的结果
    Linux真好玩阿,不过我家电脑不行,运行不够流畅
    springboot之整合JPA
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9504920.html
Copyright © 2020-2023  润新知