題解 UVA10587 【Mayor's posters】
阿新 • • 發佈:2018-08-20
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】