大致题意: 有一面墙,被等分为1QW份,一份的宽度为一个单位宽度。现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW。后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报。现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报 线段树就不说了》》主要是离散化怎么处理。。。 转: 离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9对其升序排序,得2 3 4 6 8 9 10然后建立映射2 3 4 6 8 9 10↓ ↓ ↓ ↓ ↓ ↓ ↓1 2 3 4 5 6 7那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。 离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。 User: 1013101127 Memory: 2180K Time: 610MS Language: G++ Result: Accepted Source Code #include <iostream> #include <string> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int cas; int n; int logo[100008][3]; struct poit { int pp; int num; }mem[100400*3]; int f[100008]; int ans=0; bool cmp(poit a,poit b) { return a.num<b.num; } struct node { int color; int l; int r; }p[100009]; void built(int t,int lc,int rc)//建树 { p[t].l=lc; p[t].r=rc; p[t].color=0; if(lc==rc)return ; built(2*t,lc,(lc+rc)/2); built(2*t+1,(lc+rc)/2+1,rc); } void change(int t,int lc,int rc,int col)//更新各点 { if(p[t].l==lc&&p[t].r==rc) { p[t].color=col; return ; } if(p[t].color>0&&p[t].color!=col) { p[2*t].color=p[2*t+1].color=p[t].color; p[t].color=0; } int mid=(p[t].l+p[t].r)/2; if(rc<=mid) change(2*t,lc,rc,col); else if(lc>mid) change(2*t+1,lc,rc,col); else { change(2*t,lc,mid,col); change(2*t+1,mid+1,rc,col); } } void query(int t)//查找 { if(p[t].color!=0) { if(!f[p[t].color]) { f[p[t].color]=1; ans++; } return ; } query(2*t); query(2*t+1); } int main() { cin>>cas; while(cas--) { cin>>n; for(int i=0;i<n;i++) { cin>>logo[i][0]>>logo[i][1]; mem[i*2].pp=-(i+1); mem[i*2].num=logo[i][0]; mem[i*2+1].pp=(i+1); mem[i*2+1].num=logo[i][1]; } sort(mem,mem+2*n,cmp); int tmp=mem[0].num; int sum=1; for(int i=0;i<2*n;i++) { if(mem[i].num!=tmp) { sum++; tmp=mem[i].num; } if(mem[i].pp<0) { logo[-mem[i].pp-1][0]=sum; } else { logo[mem[i].pp-1][1]=sum; } } built(1,1,sum); for(int i=0;i<n;i++) { change(1,logo[i][0],logo[i][1],i+1); } memset(f,0,sizeof(f)); ans=0; query(1); cout<<ans<<endl; } return 0; }