洛谷1558 色板游戏 线段树

我先立个Flag

我,这几天,要过1W道线段树题。

题目背景

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

题目描述

色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, ... L。现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:1. "C A B C" 指在A到 B 号方格中涂上颜色 C。2. "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)

输出格式:

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

输入输出样例

输入样例#1:

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

输出样例#1:

2

做法

开始看到这个题我想起来之前写的题解,模板]分块/可修改莫队 (数颜色种类) ,当初是单点修改颜色 询问区间颜色种类  作为练习用莫队直接过了。

这个题是 区间修改 颜色 ,由于颜色种类<=30,区间的颜色种类可以状压, 然后求和用 或运算 ,这就是一道很裸的线段树了。

洛谷这个题有坑 读入的L,R 可能有L>R  需要swap 否则爆0 (好坑啊)

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
struct Node{
    int l,r,sum;
}tree[MAXN*4];
int N,T,Q,L,R,opt,lazy[MAXN*4];
char c[5];
void build_tree(int k,int l,int r){
    tree[k].l=l,tree[k].r=r;
    if(l==r){tree[k].sum=1;return ;}
    int mid=l+r>>1;
    build_tree(k<<1,l,mid);build_tree(k<<1|1,mid+1,r);
    tree[k].sum=tree[k<<1].sum|tree[k<<1|1].sum;
}
void pushdown(int k){
    if(!lazy[k])return ;
    tree[k<<1].sum=lazy[k],lazy[k<<1]=lazy[k];
    tree[k<<1|1].sum=lazy[k],lazy[k<<1|1]=lazy[k];
    lazy[k]=0;
}
void Modify(int k,int l,int r,int x){
    if(tree[k].l>=l&&tree[k].r<=r){tree[k].sum=x,lazy[k]=x;return;}
    if(tree[k].l>r||tree[k].r<l)return ;
    pushdown(k);
    Modify(k<<1,l,r,x);Modify(k<<1|1,l,r,x);
    tree[k].sum=tree[k<<1].sum|tree[k<<1|1].sum;
}
int query(int k,int l,int r){
    if(tree[k].l>=l&&tree[k].r<=r)return tree[k].sum;
    if(tree[k].l>r||tree[k].r<l)return 0;
    pushdown(k);
    return query(k<<1,l,r)|query(k<<1|1,l,r);
}
int main()
{
    scanf("%d%d%d",&N,&T,&Q);
    build_tree(1,1,N);
    while(Q--){
        scanf("%s%d%d",c,&L,&R);
        if(L>R)swap(L,R);
        if(c[0]==‘C‘){
            scanf("%d",&opt);
            opt=(1<<opt-1);
            Modify(1,L,R,opt);
        }
        else{
            int res=query(1,L,R),ans=0;
            while(res){
                if(res&1)ans++;
                res>>=1;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
} 

吐槽

我有一个地方 k<<1|1 写成了 k<<1  查了半天改不对弃疗了,  刚刚突然一眼扫到了就给A了

班里学的物理好恶心 生无可恋。 还有 , 学考的政治历史也好烦人,不想背-_-||

时间: 2024-08-01 16:30:03

洛谷1558 色板游戏 线段树的相关文章

洛谷 [P3834] 可持久化线段树(主席树)

主席树可以存储线段树的历史状态,空间消耗很大,一般开45n即可 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <queue> #define lson l, mid #define rson mid+1, r #define ll long long using name

P1558 色板游戏 线段树(区间修改,区间查询)

题意: 给n,m,k,n长度,k个操作,m种颜色 操作C:输入A,B,C,区间[A,B]变成C颜色,可能A>B,所以要确保A<B 操作P:输入A,B,区间[A,B]的颜色种类 思路: 因为颜色只有30种,可以用位运算,然后进行lazy标记 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define il inline 5 #define it register int 6 #de

洛谷P1080 国王游戏 高精度 贪心 数学推公式

洛谷P1080 国王游戏        数学推公式      高精度    贪心 然而这并不是我打出来的,抄题解... 将左手与右手的乘积从小到大排序,然后计算求最大值即可.(需要高精度) 证明: 1)知道,如果相邻的两个人交换位置,只会影响到这两个人的值,不会影响他人 2)假设相邻的两个人i, i + 1.设A[i] B[i] <= A[i + 1] B[i + 1],i之前所有人的左手乘积为S. 则,ans1 = max{S / B[i], S * A[i] / B[i + 1]} 若交换

洛谷P1199 三国游戏 博弈论 数学

洛谷P1199 三国游戏博弈论 数学 这道题 其实 人是必胜的 能取到的最大值 为 每行第二大值中的最大值 为什么呢 假使第一次我们取到了我们心中的那个答案的所在行 那么接着电脑会取 这一行最大值的对应行 那么我们来分析一下电脑取的那个数在他取的那行的特点 首先我们假设其不是最大值,因为矩阵中任意两个数不相同 所以也就是说还有个数比他大,然后就是说电脑取的第二大或者第n大值就已经比我们取的第一大值要大了,说明我们取的行并不是每行第二大值中的最大值所在的行2.也就是说这个数必定为该行中的最大值 那

[洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?

其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当前数列的长度.(L>=0) 2. 插入操作. 语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾. 限制:n是整数(可能为负数)并且在长整

[luoguP3606] [USACO17JAN]Building a Tall Barn建谷仓(贪心 + 线段树)

传送门 把线段都读进来然后排序,先按右端点为第一关键字从小到大排序,后按左端点为第二关键字从小到大排序. 注意不能先按左端点后按右端点排序,否则会出现大包小的情况,如下: —————— ———  — 然后直接线段树搞就行,先求区间最小值,如果大于零就更新统一减1. ——代码 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #define root 1, 1, n 5 #define l

洛谷P3384 【模板】树链剖分

题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数N.M.R.P,分别表示树的结点个数.操作个数

【不可能的任务24/200】洛谷1640 bzoj1854游戏 匈牙利就是又短又快

bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个“大牛分站”,就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类似于匈牙利(⊙o⊙) (匈牙利的复杂度惊人,1e6秒过) 1 #include <cstdio> 2 bool b[3000001]; 3 int c[3000001],fir[3000001],to[3000001],nex[3000001]; 4 int N,n,p,q; 5 void add(int p,int

洛谷 P1276 校门外的树(增强版) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1276 题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树 苗也不放过(记 0 A B ,含A和B):幸运的是还有植树者每次从编号C到D 中凡是空穴(树被砍且还没种上树苗或树苗又被砍掉)的地方都补种上树苗(记 1 C D,含C和D):问最终校门外留下的树苗多少棵?植树者种上