色板游戏(线段树)

Posted 背着代码的蜗牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了色板游戏(线段树)相关的知识,希望对你有一定的参考价值。


色板游戏

题目背景:
阿宝上学了,今天老师拿来了一块很长的涂色板。
题目描述:
色板长度为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
1

思路:
线段树
区间修改就是普通的修改,关键在区间查询,即如何统计出某一区间中有多少种颜色。
写一个函数:check,如果tree[tree[k].lch].color!=tree[tree[k].rch].color,则把tree[k].color设为-1,意思是这个节点左二子和右儿子的颜色不一样。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100010;
int n,m,t,tot;
bool flag[35];
struct node

int l,r;
int lch,rch;
int flag;
int color;
tree[maxn*4];
char c;
int init()

int f=1,p=0;char c=getchar();
while(c>9||c<0)if(c==-)f=-1;c=getchar();
while(c>=0&&c<=9)p=p*10+c-0;c=getchar();
return f*p;

void build_tree(int ll,int rr)

int cur=++tot;
tree[cur].l=ll;
tree[cur].r=rr;
if(ll!=rr-1)

int mid=(ll+rr)>>1;
tree[cur].lch=tot+1;
build_tree(ll,mid);
tree[cur].rch=tot+1;
build_tree(mid,rr);
tree[cur].color=1;

else tree[cur].color=1;

void update(int k)

tree[tree[k].lch].color=tree[k].flag;
tree[tree[k].rch].color=tree[k].flag;
tree[tree[k].lch].flag=tree[k].flag;
tree[tree[k].rch].flag=tree[k].flag;
tree[k].flag=0;

void check(int k)//检查函数

if(tree[tree[k].lch].color==tree[tree[k].rch].color)
tree[k].color=tree[tree[k].lch].color;
else tree[k].color=-1;

void change(int k,int l,int r,int p)

if(l<=tree[k].l&&r>=tree[k].r)

tree[k].color=p;
tree[k].flag=p;
return;

if(tree[k].flag)
update(k);
int mid=(tree[k].l+tree[k].r)>>1;
if(l<mid) change(tree[k].lch,l,r,p);
if(r>mid) change(tree[k].rch,l,r,p);
check(k);

void find(int k,int l,int r)

if(l<=tree[k].l&&r>=tree[k].r&&tree[k].color!=-1)//注意判断

flag[tree[k].color]=1;
return;

if(tree[k].flag)
update(k);
int mid=(tree[k].l+tree[k].r)>>1;
if(l<mid) find(tree[k].lch,l,r);
if(r>mid) find(tree[k].rch,l,r);

int main()

int x,y,z;
n=init();t=init();m=init();
build_tree(1,n+1);
for(int i=1;i<=m;i++)

cin>>c;
if(c==C)

x=init();y=init();z=init();
if(x>y) swap(x,y);
change(1,x,y+1,z);

else

memset(flag,0,sizeof(flag));
int ans=0;
x=init();y=init();
if(x>y) swap(x,y);
find(1,x,y+1);
for(int j=1;j<=t;j++)
if(flag[j])
ans++;
printf("%d\\n",ans);


return 0;


以上是关于色板游戏(线段树)的主要内容,如果未能解决你的问题,请参考以下文章

色板游戏(洛谷 1558)

luogu 1558 色板游戏

Luogu P1558 色板游戏

2018年6月4号(线段树)

P1558 色板游戏

题解 P1558 色板游戏