题意: 在墙壁上贴海报,计算出看得见的张数。
题解:
线段树基础知识
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define L(u) (u<<1) #define R(u) (u<<1|1) #define W 1000000 #define N 10000 struct TreeNode { int l,r,c;}; TreeNode node[W*10]; int l[N*2], r[N*2], cood[N*3]; int ans, mark[N*2]; void build ( int u, int l, int r ) { node[u].l = l; node[u].r = r; node[u].c = 0; if ( l == r ) return; int mid = ( l + r ) >> 1; build ( L(u), l, mid ); build ( R(u), mid + 1, r ); } void update ( int u, int l, int r, int c ) { if ( node[u].c == c ) return; if ( node[u].l == l && node[u].r == r ) { node[u].c = c; return; } if ( node[u].c != -1 ) { node[L(u)].c = node[R(u)].c = node[u].c; node[u].c = -1; } int mid = (node[u].l + node[u].r) >> 1; if ( r <= mid ) update (L(u),l,r,c); else if ( l > mid ) update (R(u),l,r,c); else update (L(u),l,mid,c), update(R(u),mid+1,r,c); } void query ( int u ) { if ( node[u].c != -1 ) { if( node[u].c && !mark[node[u].c] ) { mark[node[u].c] = 1; ans++; } return; } if ( node[u].l == node[u].r ) return; query ( L(u) ); query ( R(u) ); } int bfind ( int l, int r, int num ) { while ( l <= r ) { int mid = (l+r) >> 1; if ( cood[mid] == num ) return mid; if ( num < cood[mid] ) r = mid - 1; else l = mid + 1; } return -1; } int main() { int cs, n; scanf("%d",&cs); while ( cs-- ) { scanf("%d",&n); int i, j, a, b; for (i = 1; i <= n; i++) { scanf("%d%d",&l[i],&r[i]); cood[i] = l[i]; cood[i+n] = r[i]; } sort(cood+1,cood+1+n*2); for ( i = 2, j = 1; i <= n*2; i++ ) if ( cood[i] != cood[i-1] ) cood[++j] = cood[i]; build ( 1, 1, j ); for ( i = 1; i <= n; i++ ) { a = bfind ( 1, j, l[i] ); b = bfind ( 1, j, r[i] ); update ( 1, a, b, i ); } ans = 0; memset(mark,0,sizeof(mark)); query ( 1 ); printf("%d\n",ans); } return 0; }