PKU 2777 Count Color

题目大意:

在一条直线上插入不同颜色的线段,看有多少段颜色相同的线段。
(note:加入有大神嫌题目不够详细的话 传送门:http://poj.org/problem?id=2777

输入输出格式:

给一个l(直线的长度。。直线有长度吗。。不管了。),t(颜色的种类,尽管好像并没有什么用),o(询问的次数)
“C A B C”表示在区间A,B图上C颜色, “P A B” 表示询问

A,B区间有几种不同的颜色。

分析:

用线段树,插入线段的时候,如果访问的线段已标记,则拆分为三段来插入。(这一份没有用lazy标记)

代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <cmath>
#include <cstring>
#define N 100000
using namespace std;

int flag[N];
int l,t,o,a,b,c,ans;
char k;

struct tree
{
    int l,r,cover;
}tree[N];

void build(int p,int l,int r)
{
    tree[p].l=l;
    tree[p].r=r;
    int m=(l+r)/2;
    if (r-l>1)
    {
        build(p*2,l,m);
        build(p*2+1,l,r);
    }
}

void insert(int p,int a,int b,int c)
{
    int m=(tree[p].l+tree[p].r)/2;
    printf("%d" ,l);
    if (tree[p].cover!=c)   
        if (tree[p].l==a && tree[p].r==b)
            tree[p].cover=c;
        else
        {
            if (tree[p].cover>=0)
            {
                    tree[p*2].cover=tree[p].cover;
                tree[p*2+1].cover=tree[p].cover;
                tree[p].cover=-1;               
            }
            if (b<=m)
                insert(p*2,a,b,c);
            else
            if (a>=m)
                insert(p*2+1,a,b,c);
            else
            {
                insert(p*2,a,b,c);
                insert(p*2+1,a,b,c);
            }
        }
}

int count(int p,int a, int b)
{
    if (tree[p].cover>=0)
        flag[tree[p].cover]=1;
    if (b-a>1)
    {
        count(p*2,a,(a+b)/2);
        count(p*2+1,(b+a)/2,b);
    }
}
int main()
{
    scanf("%d%d%d" ,&l,&t,&o);
    build(1,1,l);
    for (int i=1;i<=o;i++)
    {
        scanf("%c" ,&k);
        if (k=='C')
        {
            scanf("%d%d%d\n" ,&a,&b,&c);
            insert(1,a,b,c);
        }
        else
        {
            scanf("%d%d\n" ,&a,&b);
            memset(flag,0,sizeof(flag));
            ans=0;
            count(1,a,b);
            for (int j=1;j<=l;j++)
                if (flag[j]==1)         
                    ans++;
            printf("%d\n" ,ans);
            printf("%c" ,k);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值