1. 程式人生 > >題解 UVA10587 【Mayor's posters】

題解 UVA10587 【Mayor's posters】

read \n down 再看 進行 poster size name ...

先講一下:dalao @lisuier 發布的前一篇題解嚴格來講是有錯誤的

比如下一組數據:

1
3
1 10
1 4
7 10
顯然答案是3,然而用lisuier dalao的程序做出來的答案是2(後面會講錯誤原因)

簡單看出這道題用線段樹可解

so

我們用離散化+權值線段樹(戳這裏詳解)

實際上是安利自己博客

思路:建一棵空數,然後把某一區間的顏色更新為讀入的顏色;

WA,SO EASY

OK
那我們先建一棵(10^7*4)的空樹

然後

空間就炸了

正經的處理方法

對區間端點進行離散化

接下來
引用一下的 @lisuier 的話

離散化,如下面的例子,因為單位1是一個單位長度,將下面的

1 2 3 4 6 7 8 10

— — — — — — — —

1 2 3 4 5 6 7 8
離散化 X[1] = 1; X[2] = 2; X[3] = 3; X[4] = 4; X[5] = 6; X[7] =8; X[8] = 10
這樣我們就優化了空間

對一般的離散化來說,這很對,

但是

再看這一組數據

1
3
1 10
1 4
7 10

用該方法離散化後

第二張海報與第三張海報中間的間隔就消...消失了

也就是說第一張海報就看不到了(手動模擬一下發現是能看到的)

處理方法:離散化時,加到臨時數組b中的右端點+1也加到臨時數組中

看起來是這樣的

int init(){//讀入並進行離散處理
    n = read(); tot=0;
    for(int i = 1;i <= n;i++) 
        a[i].l = read(),a[i].r = read(),
        b[++tot] = a[i].l,b[++tot] = a[i].r,b[++tot] = a[i].r + 1;//加入右邊的端點+1
    sort(b + 1,b + tot + 1);
    int len=unique(b + 1,b + tot + 1) - b - 1;
    for(int i = 1; i <= n;i++) 
        a[i].l = lower_bound(b + 1,b + len + 1,a[i].l) - b,
        a[i].r = lower_bound(b + 1,b + len + 1,a[i].r) - b; //下面是正常的離散化
    return len; //離散化後總共處理多長的墻; 
}

更新之類的與普通線段樹差不多

但是要註意push_down操作和query操作

比如說詢問時已經訪問過得顏色要標記一下

接下來是

簡單易懂

的代碼.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define M 20005
using namespace std;
inline int read(){
    char chr=getchar(); int f=1,ans=0;
    while(!isdigit(chr)) {if(chr=='-') f=-1;chr=getchar();}
    while(isdigit(chr))  {ans=ans*10;ans+=chr-'0';chr=getchar();}
    return ans*f;
}
int ans = 0;
struct segment
{
int l,r;
}a[10005 << 4]; 
bool vis[20005 << 4];
struct node
{
    int l,r,val,lazy,sum;
    int mid()
    {
        return l + r >> 1;
    }
}t[M << 4];
int b[20005 << 4],n,tot=0,x,y;
int init()
{//讀入並進行離散處理
    n = read(); 
    tot = 0;
    for(int i = 1;i <= n;i++) 
        a[i].l = read(),
        a[i].r = read(),
        b[++tot] = a[i].l,
        b[++tot] = a[i].r,
        b[++tot] = a[i].r + 1;
    sort(b + 1,b + tot + 1);
    int len=unique(b + 1,b + tot + 1) - b - 1;
    for(int i = 1; i <= n;i++) 
        a[i].l = lower_bound(b + 1,b + len + 1,a[i].l) - b,
        a[i].r = lower_bound(b + 1,b + len + 1,a[i].r) - b; 
    return len; //離散化後總共處理多長的墻; 
}
void push_down(int i){
    if(t[i].val == -1)  return;
    t[i << 1].val = t[i << 1 | 1].val = t[i].val;  
    t[i].val = -1;
}
void build(int i,int l,int r)
{
    t[i].l = l;
    t[i].r = r;
    t[i].val = 0;
    if(l == r)
    {
        return;
    }
    int m=t[i].mid();
    build(i << 1,l,m);
    build(i << 1 | 1,m + 1,r);
}
void updata(int i,int l,int r,int x)
{
    if(l <= t[i].l && t[i].r <= r)
    {
        t[i].val = x;
        return;
    }
    push_down(i);
    int m = t[i].mid();
    if(l <= m)  
        updata(i << 1,l,r,x);
    if(r > m)
        updata(i << 1 | 1,l,r,x);
}
void query(int i,int l,int r)
{
    if(t[i].val != -1)
    {
         if(!vis[t[i].val])
         {
            vis[t[i].val] = 1;//做標記
            ++ans;
         }
        return;
    }
    query(i << 1,l,r);
    query(i << 1 | 1,l,r);
}

int ask(int l,int r)
{
    memset(vis,0,sizeof(vis));
    ans = 0;
    vis[0] = 1;
    query(1,l,r);
    return ans;
}

int main()
{   
    int T = read();
    while(T--)
    {
        int m=init();   tot=0;//海報染成的顏色
        build(1,1,m);
        for(int i = 1;i <= n;i++)
            updata(1,a[i].l,a[i].r,++tot);
        printf("%d\n",ask(1,m));
    }
    return 0;
}

題解 UVA10587 【Mayor's posters】