[离散化]Line Painting

针对长度为10亿的棍子,通过N次颜色覆盖操作,寻找最终最长连续白色段的有效算法实现。采用离散化处理和排序技巧,显著提高算法效率。

题目描述
有一根长度为1000000000的棍子,一开始涂成白色。
棍子上有刻度,左端点为0,右端点1000000000。
由于某种原因这根棍子的某些部分被重新涂过了。
重新涂的颜色可能是黑色或着白色。
棍子总共被依次重新涂了N(1<=N<=5000)次。
找出最后最长的白色段。

Input

第1行一个数N。
接下来N行表示一次涂色,格式如下:
ai bi ci
ai和bi为整数,ci是字母b或w。
表示把ai和bi之间那段涂成ci色(w白色,b黑色)。

0<=ai<=bi<=1000000000。

Output

一行,两个数x和y(x如果有多个最长的段,输出x最小的一个。

分析
这题数据非常大,一看就知道不能只用暴力的。
虽然离散化一般用于压缩空间,但是事实上它是时空压缩的。
于是我们离散这个x和y到b里面,然后排序b。
接着按着开始输入的顺序在b里面查找x和y,将色涂在同样离散的数组f里。
差不多了。

#include <iostream>
#include <cstdio>
using namespace std;
long long n,a[5555][2],b[11111];
char c[5555];
bool f[11111];
long long i,j,k,be,en,x,y;
void qs(int l,int h)
{
    long long i=l,j=h,mid=b[(l+h)/2],t;
    if (l>h) return;
    do
    {
        while (b[i]<mid) i++;
        while (b[j]>mid) j--;
        if (i<=j)
        {
            t=b[i];b[i]=b[j];b[j]=t;
            i++;j--;
        }
    }
    while (i<=j);
    qs(l,j);
    qs(i,h);
}
int main()
{
    scanf("%lld",&n);
    j++;
    b[j]=0;
    j++;
    b[j]=1000000000;
    a[1][0]=0;a[i][1]=1000000000;c[1]='w';
    for (i=2;i<=n+1;i++)
    {
        scanf("%lld%lld",&a[i][0],&a[i][1]);
        while (1)
        {
            scanf("%c",&c[i]);
            if (c[i]=='w'||c[i]=='b') break;
        }
        j++;
        b[j]=a[i][0];
        j++;
        b[j]=a[i][1];
    }
    qs(1,j);
    for (i=1;i<=n+1;i++)
    {
        x=1;
        while (b[x]!=a[i][0]) x++;
        y=x+1;
        while (b[y]!=a[i][1]) y++;
        if (c[i]=='b')
        {
            for (k=x;k<=y-1;k++)
            f[k]=1;
        }
        else
        for (k=x;k<=y-1;k++)
        f[k]=0;
    }
    i=0;
    while (i<j)
    {
        i++;
        if (!f[i])
        {
            x=b[i];
            i++;
            while (!f[i]&&i<j) i++;
            y=b[i];
            if (y-x>en-be)
            {
                be=x;
                en=y;
            }
        }
    }
    printf("%lld %lld",be,en);
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值