本题是个线段树的题目 听人说也是比较入门的线段树
本人新手刚学 不太了解 debug了一天
由于对线段树的结构不太了解
这里做下总结,有错误的地方望大神们指出,本人新手难免出错,望嘴下留情
线段树每次都只能前一半和后一半的区间,并不能包括所有的区间,只有由一个个的不断分成一半一半的区间来组合所有需要的区间
在我看来线段树貌似对于有些题目必须要 保持的不间断的区间的问题就有难度了
在本题中 题目意思是可以C命令把某一段区间内涂上同一颜色
P命令 可以输出某一段区间的不同颜色数
刚做本题时候 我刚线段树入门 只会想到用线段树做区间和之内的简单题目
刚看完这题的时候 对于用线段树我是没什么好方法 看了一下别人的报告
也算有所了解 这里讲一下解法
每次更新区间的值时 只要线段树的区间的左值不大于要更新的区间的右值(树的区间右值同样),那么这个树的区间至少存在2种以上的颜色,那么就把这个区间的颜色赋值给他的左右儿子,并把它置为0(至少存在2种以上颜色,所以不再考虑这个区间,而去考虑的左右儿子区间),一直到树的区间左右区间分别>=和<=要更新的左右区间,那么就把这个区间更新并return,查找的时候我出了一个错误,我还多考虑的查找的区间必须在树的区间内,才记录,这里只要查找的区间不为0且查找的区间在树的区间内就记录,用个color数组,然后统计不同的颜色数
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
int colors[50];
struct node
{
int left;
int right;
int num;
}tree[400005];
int build(int left,int right,int k)
{
tree[k].left=left;
tree[k].right=right;
tree[k].num=1;
//printf("~~~%d %d %d %d\n",tree[k].left,tree[k].right,tree[k].num,k);
if(left>=right)
{
return 1;
}
int mid=(left+right)/2;
build(left,mid,k*2+1);
build(mid+1,right,k*2+2);
return 1;
}
int update(int left,int right,int k,int color)
{
//printf("~~~~%d %d %d %d\n",left,right,tree[k].left,tree[k].right);
if(tree[k].left>right||tree[k].right<left)
return 1;
if(left<=tree[k].left&&right>=tree[k].right)
{
tree[k].num=color;
// printf("~~~~%d %d %d\n",tree[k].left,tree[k].right,tree[k].num);
return 1;
}
if(tree[k].num)
{
tree[k*2+1].num=tree[k*2+2].num=tree[k].num;
tree[k].num=0;
}
update(left,right,k*2+1,color);
update(left,right,k*2+2,color);
}
int search(int left,int right,int k)
{
// printf("k=%d %d %d %d\n",k,tree[k].left,tree[k].right,tree[k].num);
if(tree[k].left>right||tree[k].right<left)
return 1;
if(/*tree[k].left>=left&&tree[k].right<=right&&*/tree[k].num!=0)
{
//printf("!!!!%d %d %d\n",tree[k].left,tree[k].right,tree[k].num);
colors[tree[k].num]=1;
return 1;
}
search(left,right,k*2+1);
search(left,right,k*2+2);
}
int main()
{
int n,m,k;
int sum[100005];
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
build(1,n,0);
for(int i=0;i<k;i++)
{
memset(colors,0,sizeof(colors));
int left,right,color;
char sign;
scanf("%s",&sign);
if(sign=='C')
{
scanf("%d%d%d",&left,&right,&color);
if(left>right)
{
int t=left;
left=right;
right=t;
}
update(left,right,0,color);
}
else
{
scanf("%d%d",&left,&right);
int sum=0;
if(left>right)
{
int t=left;
left=right;
right=t;
}
search(left,right,0);
for(int j=1;j<=m;j++)
{
sum+=colors[j];
}
printf("%d\n",sum);
}
}
}
}