~~~~
一直MLE,才发现要写离散化操作。其他就是线段树的成段更新(每次用不同标记去更新区间),最后统计下有多少种标记就OK了。
题目链接:http://poj.org/problem?id=2528
大牛写的很详细,请戳:http://blog.csdn.net/metalseed/article/details/8041334
~~~~
#include<cstdio> #include<cstring> #include<algorithm> #define N 11111 #define lson rt<<1,s,m #define rson rt<<1|1,m+1,e using namespace std; int x[N<<2]; //因为有离散化操作,注意数组大小,否则会RE。 int ans[N<<2]; int s[N],e[N]; int tre[N<<4]; void pushdown(int rt,int m) { if(tre[rt]) { tre[rt<<1]=tre[rt<<1|1]=tre[rt]; tre[rt]=0; } } void update(int l,int r,int val,int rt,int s,int e) { if(l<=s && r>=e) { tre[rt] = val; return ; } pushdown(rt,e-s+1); int m=(s+e)>>1; if(r<=m) update(l,r,val,lson); else if(l>m) update(l,r,val,rson); else { update(l,m,val,lson); update(m+1,r,val,rson); } } int query(int pos,int rt,int s,int e) { if(s==e) return tre[rt]; pushdown(rt,e-s+1); int m=(s+e)>>1; if(pos<=m) query(pos,lson); else query(pos,rson); } int bin(int key,int ma) { int l=0,r=ma,m=0; while(l<=r) { m=(l+r)>>1; if(x[m]==key) return m; else if(x[m]>key) r=m-1; else l=m+1; } //return -1; } int main() { int t; scanf("%d",&t); while(t--) { int m; scanf("%d",&m); int n=0; for(int i=1;i<=m;i++) { scanf("%d%d",&s[i],&e[i]); x[n++]=s[i]; x[n++]=e[i]; } int cnt=1; sort(x,x+n); //删去重复的元素, for(int i=1;i<n;i++) if(x[i]!=x[i-1]) x[cnt++]=x[i]; //离散化技巧:凸显间隔(否则可能会有问题)。 for(int i=cnt-1;i>0;i--) if(x[i]!=x[i-1]+1) x[cnt++]=x[i-1]+1; //再一次排序,便于后面二分离散化。 sort(x,x+cnt); memset(tre,0,sizeof(tre)); //相当于建树过程 for(int i=1;i<=m;i++) { int l=bin(s[i],cnt-1); int r=bin(e[i],cnt-1); update(l,r,i,1,0,cnt-1); //依次标记 } int q=0; for(int i=0;i<cnt;i++) { int k=query(i,1,0,cnt-1); if(k) ans[q++]=k; //~~ } sort(ans,ans+q); int tot=1; for(int i=1;i<q;i++) if(ans[i]!=ans[i-1]) tot++; printf("%d\n",tot); } return 0; }
POJ 2528 Mayor's posters.,布布扣,bubuko.com
POJ 2528 Mayor's posters.
时间: 2024-10-14 05:18:07