题意:有一长度为10000000的墙,上面按时间顺序张贴长度不同,宽度相同,位置不一定相同的广告,问最终还能有多少广告能露出来。
分析:线段树。每贴一张海报就是把一个连续的区间的值全部更改,但这里的数据比较大,直接做可能时间空间复杂度都很高。因为最多只有10000张海报,而即使每张海报的两个端点都不相同,最多就有20000个有用的端点,所以可以采用映射把这些位置离散化,把这些点由小到大映射到另一个数组里,然后的线段树的操作就可以只在这个数组里进行了。
#include<cstdio> #include<algorithm> using std::sort; struct line { int from,pos; bool operator < (line b) const { return pos<b.pos; } }; struct node { int lchild,rchild; int lend,rend; int color; }; int coordinate[100001][2],m,t,last; line l[200001]; node tree[200001]; bool tag[200001];//标记有无lazy void make_map(int i,int& m) { if(l[i].pos!=l[last].pos) { last=i; m++; } if(l[i].from<0) coordinate[-l[i].from-1][1]=m; else coordinate[l[i].from-1][0]=m; } void lazy(int pos,int x) { tag[pos]=true; tree[pos].color=x; } //前提tag[pos]==true void unlazy(int pos) { if(tree[pos].rchild!=tree[pos].lchild)//不是叶子 { lazy(tree[pos].lchild,tree[pos].color); lazy(tree[pos].rchild,tree[pos].color); } tag[pos]=false; } int initTree(int a,int b) { int num=++t; tag[num]=false; tree[num].color=-1; tree[num].lend=a; tree[num].rend=b; if(a==b) { tree[num].lchild=-1; tree[num].rchild=-1; return num; } int mid=(a+b)/2; tree[num].lchild=initTree(a,mid); tree[num].rchild=initTree(mid+1,b); return num; } void insert(int pos,int left,int right,int x) { if(pos<0) return; if(left<=tree[pos].lend && right>=tree[pos].rend)//此次目标操作区间完全覆盖此区间 lazy(pos,x); else { if(!(tree[pos].lend>right || tree[pos].rend<left))//有交集(不一定包含目标操作区间) { if(tag[pos])//有标记 unlazy(pos); tree[pos].color=-1; insert(tree[pos].lchild,left,right,x); insert(tree[pos].rchild,left,right,x); } } } void dfs(int a,int& counter) { if(tree[a].color==-1 && tree[a].lchild!=tree[a].rchild) { dfs(tree[a].lchild,counter); dfs(tree[a].rchild,counter); } else if(!tag[tree[a].color]) { tag[tree[a].color]=true; counter++; } } int main() { int c; scanf("%d",&c); while(c--) { int n; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d%d",&coordinate[i][0],&coordinate[i][1]); l[2*i].pos=coordinate[i][0]; l[2*i].from=i+1; l[2*i+1].pos=coordinate[i][1]; l[2*i+1].from=-i-1; } //make a map sort(l,l+2*n); m=1; last=0; for(int i=0;i<2*n;i++) make_map(i,m); /*printf("m=%d\n",m); for(int i=0;i<n;i++) { printf("coordinate[%d][0]=%d,coordinate[%d][1]=%d\n",i,coordinate[i][0],i,coordinate[i][1]); }*/ //initial tree t=-1; initTree(1,m); t++; //insert the intervals for(int i=0;i<n;i++) insert(0,coordinate[i][0],coordinate[i][1],i); //count the posters int counter=0; for(int i=0;i<n;i++) tag[i]=false; //preorder traverse dfs(0,counter); printf("%d\n",counter); } return 0; }