poj 2528
Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
题意:贴报纸,可以互相覆盖,求最后能看见多少。
数据很大,不离散会超出内存。将浪费的部分去掉,将出现过的所有点其映射到相距更近的点上。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; typedef long long ll; #define N 100005 #define mod 258280327 #define MIN 0 #define MAX 1000001 int l[N],r[N]; int x[N]; int has[10000005]; struct node { int le,re; bool covered; } pnode[10*N]; void build(int i,int l,int r) { pnode[i].le = l; pnode[i].re = r; pnode[i].covered = false; if(l == r) return; build(2 * i,l,(l+r)/2); build(2*i+1,(l+r)/2+1,r); } bool insert(int i,int l,int r,int a,int b)//是否可见 { if(pnode[i].covered == true)//如果要找的已经被覆盖 return false; if(l == a && r == b) { pnode[i].covered = true; return true; } bool ans; int mid = (l + r)>>1; if (mid >= b) ans = insert(i*2,l, mid, a, b); else if (mid < a) ans = insert(i*2+1,mid+1, r, a, b); else { bool x1 = insert(i*2,l, mid, a, mid); bool x2 = insert(i*2+1,mid+1, r, mid+1, b); ans = x1 || x2; } if(pnode[i*2].covered == true && pnode[i*2+1].covered == true) pnode[i].covered = true; return ans; } int main() { int T,n,tot; scanf("%d",&T); while(T--) { scanf("%d",&n); tot = 0; for(int i = 1; i <= n; i++) { scanf("%d%d",&l[i],&r[i]); x[tot++] = l[i]; x[tot++] = r[i]; } sort(x,x+tot); tot = unique(x,x+tot)-x; int all=1; for(int i = 0;i < tot;i++) { has[x[i]] = all; if(i < tot - 1) { if(x[i+1] - x[i] == 1) all++; else all+=2; } } build(1,1,all); int num = 0; for(int i = n;i >=1;i--) { if(insert(1,1,all,has[l[i]],has[r[i]])) num ++; } printf("%d\n",num); } return 0; }