POJ2528
题大意为在一片等高长度为10000000的墙上粘贴n(n<=10000)份海报,在相同区间内后粘贴的海报会覆盖之前海报,求所有操作结束后有多少张海报未被完全覆盖。
Sample Input
1
5
1 4
2 6
8 10
3 4
7 10
Sample Output
4
因为题目的数据规模较大,直接建立线段树会使用过高的空间并造成极大的空间浪费,所以需要对数据进行离散化处理。但是要注意,若直接对题目输入数据进行处理成点集则会出现异常,如
3
1 10
1 3
6 10
这组数据的结果显然为3,但直接离散化后则变为
1 4
1 2
3 4
自然得到的输出结果为错误的2,而原数据中的(3,6)这一区间内的点则被离散化后忽略了。我选择的处理方法为在离散化的同时,判断相邻数据是否相差大于1,是则将其和的一半加入到离散化数据中去。如1 10这组数据相差为9,则将(1+10)/2==5加入到数据处理中。这种情况下加入的数据并不参与实际计算,仅作为标识代表线段中点。
建树则是直接建立的求区间和的线段树。叶节点权值仅为0或1,代表当前节点是否已被覆盖。区间和则代表该区间已被覆盖的叶子节点数。若当前区间的值不为(right-left)即区间内叶子节点的数量,则代表该区间仍存在可以覆盖的点。因此,只需在处理数据时,逆向处理。因为最后粘贴的海报必然未被覆盖,而之前的数据只需要在相对应的区间内寻找是否存在未被后来者覆盖的点。存在则值自加。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int temp[300000];
int a[300000];
const int INF = -9999999;
int counts,flag;
class tree
{
public:
int left,right;
int val;
int lazy;
};
tree segtree[6000000];
void bulidetree(int node,int left,int right)
{
segtree[node].left=left;
segtree[node].right = right;
segtree[node].lazy=0;
if(left==right)
{
segtree[node].val = 0;
return ;
}
bulidetree(node*2,left,(left+right)/2);
bulidetree(node*2+1,(left+right)/2+1,right);
segtree[node].val = segtree[node*2].val+segtree[node*2+1].val;
}
void pushdown(int n)
{
if(segtree[n].lazy)
{
segtree[n*2].val = (segtree[n*2].right-segtree[n*2].left+1)*segtree[n].lazy;
segtree[n*2+1].val = (segtree[n*2+1].right-segtree[n*2+1].left+1)*segtree[n].lazy;
segtree[n*2].lazy = segtree[n].lazy;
segtree[n*2+1].lazy=segtree[n].lazy;
segtree[n].lazy=0;
}
}
void update(int n,int begin,int end,int left,int right)
//查找对应区间并进行区间更新
{
if(begin>right||end<left)
{
return;
}
pushdown(n);
if(left<=begin&&end<=right)
{
if(segtree[n].val<(segtree[n].right-segtree[n].left+1))
{
segtree[n].val=(segtree[n].right-segtree[n].left+1);
segtree[n].lazy = 1;
if(flag==0)
{
flag++;
counts++;
}
}
return;
}
update(n*2,begin,(begin+end)/2,left,right);
update(n*2+1,(begin+end)/2+1,end,left,right);
segtree[n].val = segtree[n*2].val+segtree[n*2+1].val;
}
int main()
{
int i,j,k,n,t,max_;
scanf("%d",&t);
while(t--)
{
counts =0;
max_= INF;
scanf("%d",&n);
j = n*2;
for(i=0;i<n;i++)
{
scanf("%d%d",&a[i*2],&a[i*2+1]);
temp[i*2] = a[i*2];
temp[i*2+1] = a[i*2+1];
if(temp[i*2+1]-temp[i*2]>1)
temp[j++]=temp[i*2+1]-temp[i*2];
}
sort(temp,temp+j);
int size_ = unique(temp,temp+j) - temp;
for(i=0;i<n;i++) //离散化处理
{
a[i*2]=(lower_bound(temp,temp+size_,a[i*2])-temp)+1;
a[i*2+1]=(lower_bound(temp,temp+size_,a[i*2+1])-temp)+1;
if(a[i*2]>max_)
{
max_= a[i*2];
}
if(a[i*2+1]>max_)
{
max_= a[i*2+1];
}
}
bulidetree(1,0,max_-1);
for(i=n-1;i>=0;i--) //从后往前处理数据
{
flag =0;
update(1,0,max_-1,a[i*2]-1,a[i*2+1]-1);
}
printf("%d\n",counts);
}
return 0;
}