色板游戏(线段树)
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;
以上是关于色板游戏(线段树)的主要内容,如果未能解决你的问题,请参考以下文章