(中等) POJ 2528 Mayor's posters , 离散+线段树。
Description
The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for placing the posters and introduce the following rules:
They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections.
Your task is to find the number of visible posters when all the posters are placed given the information about posters' size, their place and order of placement on the electoral wall.
- Every candidate can place exactly one poster on the wall.
- All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown).
- The wall is divided into segments and the width of each segment is one byte.
- Each poster must completely cover a contiguous number of wall segments.
They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections.
Your task is to find the number of visible posters when all the posters are placed given the information about posters' size, their place and order of placement on the electoral wall.
题目大致就是说给一个线段覆盖线段,问最后没有被完全覆盖的线段的个数。
这是第一次写离散,也是第三次写线段树的区间更新,想了好久,发现是个空线段树,只需要COL,即标记,不需要BIT来保存啥数据。
离散的话是因为数据范围太大,只取用到的,排序后分别编号为1...N ,再用。
(注:这个题要注意,离散的话比如3和7分别标号为4和5的话,那么如果第一个覆盖1-20,第二个覆盖1-3 , 另一个覆盖 7-10 的话,那么编号4和5都被覆盖,结果将为2,而不是正确的3 。 所以可以按照杭电那位大神的处理方法,只要3和7之间超过1,那么再加一个数4,这样的话分别编号为4,5,6就好了。)
标记记录每次更新的为编号几。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define lson L,M,po*2 #define rson M+1,R,po*2+1 using namespace std; int COL[40004*4]; int num[20004]; int num1[20004]; int rnum[40004]; int cou; bool vis[10004]; int findH(int x,int L,int R) { int M=(L+R)/2; if(rnum[M]==x) return M; if(rnum[M]<x) return findH(x,M+1,R); else return findH(x,L,M); } void pushDown(int po) { if(COL[po]) { COL[po*2]=COL[po]; COL[po*2+1]=COL[po]; COL[po]=0; } } void update(int ul,int ur,int cha,int L,int R,int po) { if(ul<=L&&ur>=R) { COL[po]=cha; return; } pushDown(po); int M=(L+R)/2; if(ul<=M) update(ul,ur,cha,lson); if(ur>M) update(ul,ur,cha,rson); } void query(int L,int R,int po) { if(L==R) { if(COL[po]) vis[COL[po]]=1; return; } pushDown(po); int M=(L+R)/2; query(lson); query(rson); } int main() { int T,N; int a,b; int ans=0; cin>>T; while(T--) { memset(COL,0,sizeof(COL)); memset(vis,0,sizeof(vis)); scanf("%d",&N); ans=0; for(int i=0;i<N;++i) { scanf("%d %d",&num[i*2],&num[i*2+1]); num1[i*2]=num[i*2]; num1[i*2+1]=num[i*2+1]; } sort(num,num+2*N); rnum[0]=num[0]; cou=1; for(int i=1;i<N*2;++i) { if(num[i]==num[i-1]) continue; if(num[i]-num[i-1]>1) rnum[cou++]=num[i-1]+1; rnum[cou++]=num[i]; } for(int i=0;i<N;++i) { a=findH(num1[i*2],0,cou-1); b=findH(num1[i*2+1],0,cou-1); update(a+1,b+1,i+1,1,cou,1); } query(1,cou,1); for(int i=1;i<=N;++i) if(vis[i]) ++ans; printf("%d\n",ans); } return 0; }