count color

本题是个线段树的题目 听人说也是比较入门的线段树

本人新手刚学 不太了解 debug了一天

由于对线段树的结构不太了解

这里做下总结,有错误的地方望大神们指出,本人新手难免出错,望嘴下留情

线段树每次都只能前一半和后一半的区间,并不能包括所有的区间,只有由一个个的不断分成一半一半的区间来组合所有需要的区间

在我看来线段树貌似对于有些题目必须要 保持的不间断的区间的问题就有难度了

在本题中 题目意思是可以C命令把某一段区间内涂上同一颜色

P命令 可以输出某一段区间的不同颜色数

刚做本题时候 我刚线段树入门 只会想到用线段树做区间和之内的简单题目

刚看完这题的时候 对于用线段树我是没什么好方法 看了一下别人的报告

也算有所了解 这里讲一下解法

每次更新区间的值时 只要线段树的区间的左值不大于要更新的区间的右值(树的区间右值同样),那么这个树的区间至少存在2种以上的颜色,那么就把这个区间的颜色赋值给他的左右儿子,并把它置为0(至少存在2种以上颜色,所以不再考虑这个区间,而去考虑的左右儿子区间),一直到树的区间左右区间分别>=和<=要更新的左右区间,那么就把这个区间更新并return,查找的时候我出了一个错误,我还多考虑的查找的区间必须在树的区间内,才记录,这里只要查找的区间不为0且查找的区间在树的区间内就记录,用个color数组,然后统计不同的颜色数

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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=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&&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;iright)
               {
                   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);
           }
       }
   }
}





你可能感兴趣的:(poj,线段树,数据结构)