sdut 2427 Mayor\'s posters(线段树+离散化)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2427
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 #define MAX 20001 6 using namespace std; 7 8 struct node 9 { 10 int li; 11 int num; 12 }st[MAX*4];//用于离散化的数组 13 int tree[MAX*4]; 14 int ht[MAX][2];//用于存储端点的数组 15 int vis[MAX],sum; 16 bool cmp(node a,node b) 17 { 18 return a.li<b.li; 19 } 20 void build(int l,int r,int w) 21 { 22 if(l==r) 23 { 24 tree[w]=0;//端点值为0 25 return ; 26 } 27 int m=(l+r)/2; 28 build(l,m,w*2); 29 build(m+1,r,w*2+1); 30 } 31 void update(int L,int R,int l,int r,int w, int x) 32 { 33 if(L==l&&R==r) 34 { 35 tree[w]=x;//标记 36 return ; 37 } 38 if(tree[w]>0&&tree[w]!=x) 39 { 40 tree[w*2+1]=tree[w*2]=tree[w];//向下传递 41 tree[w]=0;//删除标记 42 } 43 int m=(l+r)/2; 44 if(L>m) 45 update(L,R,m+1,r,w*2+1,x); 46 else if(R<=m) 47 update(L,R,l,m,w*2,x); 48 else 49 { 50 update(L,m,l,m,w*2,x); 51 update(m+1,R,m+1,r,w*2+1,x); 52 } 53 } 54 void query(int w) 55 { 56 if(tree[w]!=0) 57 { 58 if(!vis[tree[w]]) 59 { 60 vis[tree[w]]=1;//标记 61 sum++; 62 } 63 return ; 64 } 65 query (w*2); 66 query(w*2+1); 67 } 68 int main() 69 { 70 int t,n,i; 71 scanf("%d",&t); 72 while(t--) 73 { 74 scanf("%d",&n); 75 for(i=0;i<n;i++) 76 { 77 scanf("%d%d",&ht[i][0],&ht[i][1]); 78 st[2*i].li=ht[i][0]; 79 st[2*i].num=-(i+1);//负号 记录左面的端点 80 st[2*i+1].li=ht[i][1]; 81 st[2*i+1].num=i+1;//记录右面端点 82 } 83 sort(st,st+n*2,cmp); 84 int temp=st[0].li,tp=1;//按小到大离散,tp标记 85 for(i=0;i<2*n;i++) 86 { 87 if(st[i].li!=temp)//判断是否重复 88 { 89 tp++; 90 temp=st[i].li; 91 } 92 if(st[i].num<0)//是否为左端点 93 { 94 ht[-st[i].num-1][0]=tp; 95 } 96 else 97 { 98 ht[st[i].num-1][1]=tp; 99 } 100 } 101 build(1,tp,1); 102 memset(vis,0,sizeof(vis)); 103 for(i=0;i<n;i++) 104 { 105 update(ht[i][0],ht[i][1],1,tp,1,i+1);//防止i=0情况 106 } 107 sum=0; 108 query(1); 109 printf("%d\n",sum); 110 } 111 return 0; 112 }