标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 59683 | Accepted: 17296 |
Description
Input
Output
Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
Source
题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报 思路:这题数据范围很大,直接搞超时+超内存,需要离散化: 离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了 所以离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多 而这题的难点在于每个数字其实表示的是一个单位长度(并且一个点),这样普通的离散化会造成许多错误(包括我以前的代码,poj这题数据奇弱) 给出下面两个简单的例子应该能体现普通离散化的缺陷: 1-10 1-4 5-10 1-10 1-4 6-10 为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10] 如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了. 线段树功能:update:成段替换 query:简单hash
说一下离散化,用map完美TLE,改成1e7大数组因为memset太耗时,再改成二分搜索用下标快好多
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> using namespace std; const int N=1e4+10,TREE=4e4+5; #define m (l+r)/2 #define lson o<<1,l,m #define rson o<<1|1,m+1,r #define lc o<<1 #define rc o<<1|1 inline int read(){ char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } //map<int,int> mp; //int mp[10000009]; int mp[N<<2]; int t[TREE<<2]; int T,n,ll[N],rr[N],a[N<<1]; inline void paint(int o,int v){ t[o]=v; } inline void pushDown(int o){ if(t[o]!=0){ paint(lc,t[o]); paint(rc,t[o]); t[o]=0; } } void draw(int o,int l,int r,int ql,int qr,int v){//printf("draw %d %d %d\n",o,l,r); if(ql<=l&&r<=qr) paint(o,v); else{ pushDown(o); if(ql<=m) draw(lson,ql,qr,v); if(m<qr) draw(rson,ql,qr,v); } } int vis[N],ans=0; void query(int o,int l,int r,int ql,int qr){//printf("quer %d %d %d\n",o,l,r); if(t[o]){ if(!vis[t[o]]){ans++;vis[t[o]]=1;} }else{ if(l==r) return; if(ql<=m) query(lson,ql,qr); if(m<qr) query(rson,ql,qr); } } int main(){ T=read(); while(T--){ n=read(); memset(t,0,sizeof(t)); //mp.clear(); //memset(mp,0,sizeof(mp)); for(int i=1;i<=n;i++){ll[i]=read();rr[i]=read();a[2*i-1]=ll[i];a[2*i]=rr[i];} sort(a+1,a+1+2*n); int cnt=0; // mp[a[1]]=++cnt; // for(int i=2;i<=2*n;i++) // if(a[i]!=a[i-1]){ // //if(!mp.count(a[i]-1)) mp[a[i]-1]=++cnt; // if(!mp[a[i]-1]) mp[a[i]-1]=++cnt; // mp[a[i]]=++cnt; // } // for(int i=1;i<=n;i++){ // int ql=mp[ll[i]],qr=mp[rr[i]];//printf("hi %d %d\n",ql,qr); // draw(1,1,cnt,ql,qr,i); // } // for(int i=1;i<=2*n;i++) if(a[i]!=a[i-1]) mp[++cnt]=a[i]; for(int i=cnt;i>=1;i--) if(mp[i]!=mp[i-1]+1) mp[++cnt]=mp[i-1]+1; sort(mp+1,mp+1+cnt); for(int i=1;i<=n;i++){ int ql=lower_bound(mp+1,mp+1+cnt,ll[i])-mp,qr=lower_bound(mp+1,mp+1+cnt,rr[i])-mp; draw(1,1,cnt,ql,qr,i); } ans=0; memset(vis,0,sizeof(vis)); query(1,1,cnt,1,cnt); printf("%d\n",ans); //printf("\n\ncnt %d\n",cnt); //for(int i=1;i<=10;i++) printf("mp %d %d\n",i,mp[i]); } }
POJ2528Mayor's posters[线段树 离散化]
标签:
原文地址:http://www.cnblogs.com/candy99/p/5954776.html