涂色

Description

有一根长度为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最小的一个。

Sample Input

4
1 999999997 b
40 300 w
300 634 w
43 47 b

Sample Output

47 634

分析
将所有数离散到数组里,然后暴力进行一下枚举
注意:一开始所有都是白色的

程序:

#include<iostream>
using namespace std;
int l[10003],a[5002],b[5002],n;
char color[10003],c[5002],s;
void kp(int l,int r);
void work();
int main()
{
    cin>>n;
    n++;
    a[1]=0;b[1]=1000000000;
    c[1]='w';
    l[1]=0;l[2]=b[1];
    for (int i=2;i<=n;i++)
    {
        cin>>a[i]>>b[i]>>c[i];
        l[i*2-1]=a[i];
        l[i*2]=b[i];
    }
    kp(1,2*n);
    work();
    return 0;
}
void kp(int l1,int r)
{
    int i,j,mid,t;
    i=l1;j=r;mid=l[(i+j)/2];
    do
    {
        while (l[i]<mid) i++;
        while (l[j]>mid) j--;
        if (i<=j) 
        {
            t=l[i];l[i]=l[j];l[j]=t;
            i++;j--;
        }
    }
    while (i<j);
    if (l1<j) kp(l1,j);
    if (i<r) kp(i,r);
}
void work()
{
    int ans,ansi,ansj,ti,tj,now;
    for (int i=1;i<=2*n-1;i++)
    {
        for (int j=1;j<=n;j++)
        if (l[i]>=a[j]&&l[i+1]<=b[j]) color[i]=c[j];
    }
    ans=0;
    int i=1;
    char s='w';
    do
    {
        if (color[i]==s)
        {
            ti=i;
            tj=ti+1;
            now=0;
            while (color[tj]==s&&tj<=2*n)
            {
                now=now+l[tj]-l[tj-1];
                tj=tj+1;
            }
            now=now+l[tj]-l[tj-1];
            if (now>ans)
            {
                ans=now;
                ansi=ti;
                ansj=tj;
            }
            i=tj;
        }
        i++;
    }
    while (i<2*n);
    cout<<l[ansi]<<' '<<l[ansj];
}
原文地址:https://www.cnblogs.com/YYC-0304/p/9500018.html