程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> ZOJ2301(HDU1199) Color the Ball(離散化)

ZOJ2301(HDU1199) Color the Ball(離散化)

編輯:C++入門知識

題意是說,有從 1 開始遞增依次編號的很多球,開始他們都是黑色的,現在依次給出 n 個操作(ai,bi,ci),每個操作都是把編號 ai 到 bi 區間內的所有球塗成 ci 表示的顏色(黑 or 白),然後經過 n 次給定的操作後,求最長的連續白色區間的左端點和右端點。
這裡有個技巧,就是我們不用記錄所有黑色區間的信息,黑色區間的信息只是用來更新白色區間的。需要記錄的是每個白色區間的左端,右端。
也就是說,對於每個塗白操作,我們就直接把這個區間記錄下來;而對於每個塗黑操作,我們看他是否會對現有的所有白色區間產生影響,如果不會,直接忽略掉,如果這個塗黑操作對現有的白色區間產生了影響(比如一個黑色區間覆蓋了一個白色區間的一部分,或者一個黑色區間出現在已有的一個白色區間中間,把他分割成了倆個白色區間),那麼就要調整現有的白色區間的左值、右值。

最後,遍歷保存的所有白色區間,同時合並相交,或者相接的區間,找到最大值

Thanks: 
[cpp] 
#include<stdio.h> 
#include<stdlib.h> 
 
#define N 2010 
int cnt; 
 
struct Node{ 
    int left,right; 
}in[N]; 
 
int cmp(const void *a,const void *b){ 
    struct Node *c=(Node *)a; 
    struct Node *d=(Node *)b; 
    return c->left - d->left; 

 
void swap(int &a,int &b){ 
    if(a>b){ 
        int tmp=a; a=b; b=tmp; 
    } 

 
void white(int a,int b){ 
    in[cnt].left = a; 
    in[cnt++].right = b; 

 
void black(int a,int b){ 
    //PS :in[N]裡面保存的都是白色區間 
    int i,tmp = cnt; 
    for(i=0;i<tmp;i++){ 
        if(in[i].left < a){ 
             
            if(in[i].right >= a){ 
                //即將插入的黑色區間和 in[i] 區間有交集,覆蓋掉了 in[i] 的一部分,並沒有新增白色區間個數 
                if(in[i].right <= b){ 
                    in[i].right = a-1; 
                } 
                //第 in[i] 個白色區間的右值比 b 小,也就是說即將插入的黑色區間把 in[i] 分割成了兩個區間 
                else { 
                    in[cnt].left = b+1; 
                    in[cnt++].right = in[i].right; 
 
                    in[i].right = a-1; 
                } 
            } 
             
        } 
        else if(in[i].left <= b){ 
            //同上 
            if(in[i].right <= b){// in[i] 被即將插入的黑色區間完全覆蓋 
                in[i].left = 0;//標志位,表示該區間是否還存在白點 
                in[i].right = -1;//目測是為了方便計算區間長度而定為 -1 的 
            } 
            else {//覆蓋了一部分,只需要修改邊界即可 
                in[i].left = b+1; 
            } 
 
        } 
    } 

 
int main() 

    int a,b,n,i,index; 
    char op[3]; 
    while(~scanf("%d",&n)){ 
        //memset(in,0,sizeof(in)); 
        cnt = 0; 
        for(i=0;i<n;i++){ 
            scanf("%d%d%s",&a,&b,op); 
            swap(a,b); 
 
            if(op[0]=='w')white(a,b); 
            else black(a,b); 
        } 
 
        index = 0; 
        qsort(in,cnt,sizeof(in[0]),cmp); 
        int max = in[0].right-in[0].left+1; 
        for(i = 1;i<cnt;i++){ 
            if(in[i].left != 0){ 
                if(in[i].left <= in[i-1].right+1){ 
                    if(in[i-1].right <= in[i].right){//相當於 相交(或相接)的兩個白色區間合並 
                        in[i].left = in[i-1].left; 
                    } 
                    else {//這裡是必須的,in[i] 是為了 in[i+1] 更新的 
                        in[i].left = in[i-1].left; 
                        in[i].right = in[i-1].right; 
                    } 
                } 
            } 
 
            (in[i].right-in[i].left+1 > max) ? (max = in[i].right-in[i].left+1 , index=i) : max; 
        } 
        max == 0 ? puts("Oh, my god") : printf("%d %d\n",in[index].left,in[index].right); 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved