poj 2528 3277 線段樹 海報覆蓋

2021-06-22 21:14:39 字數 3834 閱讀 5368

題意:給定一些海報,可能互相重疊,告訴你每個海報的起始和終止座標(高度都一樣)和先後疊放次序,問沒有被完全蓋住(露出)的海報有多少張。

思路(部分內容摘自poj課件):線段樹+離散化。節點增添flag域,用來表示該段是否已經被覆蓋。

如果每個葉子節點都代表一塊瓷磚,那麼線段樹會導致mle。實際上,由於最多10,000個海報,共計20,000個端點,這些端點把牆最多分成19,999個單位區間,我們只要對這19,999個區間編號,然後建樹即可。這就是離散化。

更好的離散化方法,是將所有海報的端點瓷磚排序,把每個海報的端點瓷磚都看做乙個單位區間,兩個相鄰的端點瓷磚之間的部分是乙個單位區間。這樣最多會有20000 + 19999個單位區間。

另外注意,插入的順序為從上至下,這樣後插入的海報不可能覆蓋先插入的海報,因此插入一張海報時,如果發現海報對應區間有一部分露出來,就說明該海報部分可見。

用陣列開線段樹比較奇葩,g++ac,c++則wa。原因不明啊,老師說可能是陣列越界,但是我通過進行二分查詢而避免開那個10000000的hash陣列來求區間(見版本3),仍然是g++ac,c++wa....

poj3277的意思是給定每個矩形的高度以及底邊在數軸上的起點和終點。各矩形間可能有重疊。問它們覆蓋的總面積是多少。思路同2528。需要注意的是初始化要按照h從小到大排序。

#include #include #include #define n 10100

typedef struct nodetree;

int t,n,top,len,res;

int poster[n][2];//儲存海報端點,逆序更新

int s[n*2];//海報的端點瓷磚編號,用於排序

int hash[10000010];//hash[i]表示瓷磚端點為i所處的離散化後的區間編號

tree t[n*100];

tree *root,*alloc;

int cmp(const int *a,const int *b)

int getmid(tree *r)

void create(tree *r,int l,int r)

}int update(tree *r,int l,int r)

else if(r <= mid)

temp = update(r->lson,l,r);

else if(l > mid)

temp = update(r->rson,l,r);

else

if(!r->lson->flag && !r->rson->flag)//要更新根節點的覆蓋情況,不更新會出錯

r->flag = 0;

return temp;

}int main()

create(root,1,top);

for(i = n-1;i>=0;i--)

res += update(root,hash[poster[i][0]],hash[poster[i][1]]);

printf("%d\n",res);

} return 0;

}

陣列版本:

#include #include #include #include #define n 10005

#define inf 0x3fffffff

using namespace std;

int hh[10000005];

struct treet[n*4];

int p[n][2],s[n<<1];

int n,t,len,m;

int mid(int a,int b)

void createtree(int root,int a,int b)

}bool insert(int root,int a,int b)

if(b <= mm)

res = insert(root*2, a, b);

else if(a>mm)

res = insert(root*2+1, a, b);

else

if(t[root*2].flag && t[root*2+1].flag)

t[root].flag = true;

return res;

}int main()

sort(s,s+len);

for(i = j = 0;i1)//必不可少,想想如下例子:三個海報,順序:(6,8)(4,6)(8,10)

++m;

}createtree(1,1,m);

for(i = n;i>=1;i--)

printf("%d\n",res);

}return 0;

}

版本3:數組建線段樹,採用二分查詢找到區間,不開一千萬的hash陣列:

#include #include #include #include #define n 10005

#define inf 0x3fffffff

using namespace std;

struct treet[n<<4];

int p[n][2],s[n<<1],hh[n<<2];

int n,t,len,m;

int mid(int a,int b)

void createtree(int root,int a,int b)

}bool insert(int root,int a,int b)

if(b <= mm)

res = insert(root*2, a, b);

else if(a>mm)

res = insert(root*2+1, a, b);

else

if(t[root*2].flag && t[root*2+1].flag)

t[root].flag = true;

return res;

}int find(int x)

return 0;

}int main()

sort(s,s+len);

for(i = j = 0;i1)//必不可少,想想如下例子:三個海報,順序:(6,8)(4,6)(8,10)

hh[++m] = s[i]-1;

hh[++m] = s[i];

}createtree(1,1,m);

for(i = n;i>=1;i--)

printf("%d\n",res);

}return 0;

}

3277:

#include #include #include #include #include #include using namespace std;

#define clc(s,t) memset(s,t,sizeof(s))

#define inf 0x3fffffff

#define n 70005

struct nodep[n];

struct treet[n<<3];

int s[n<<1],n,m;

int mid(int x,int y)

void create(int root,int l,int r)

void update(int r,int a,int b,int h)

if(t[r].h)

if(b<=mm)

update(r*2, a, b, h);

else if(a>mm)

update(r*2+1, a, b, h);

else

}long long area(int r)

int cmp(node a,node b){

return a.h

線段樹模板 poj2777

線段數塗色 include include using namespace std define maxn 100005 struct node tree maxn 4 bool visit 40 int sum void build int left,int right,int id tree i...

poj3468之線段樹

include include include include include include include include include define inf 99999999 using namespace std const int max 100000 10 int64 sum max ...

線段數應用 poj2828

線段數應用 題目 buy tickets 題目大意 n個人排隊等待,第 i個人到來會有兩個資訊 pos i 0,i 1 val i 表明這 個人會插隊到 pos i 的後邊,這個人的值是 val i 依次給出 n個人的到來資訊,輸出最終的 佇列從頭到尾每個人的值。思路 第 i個人插入的位置是 pos...