文章目录
题目链接:
http://poj.org/problem?id=2528
题意:就是有 N 种海报,每种海报有个长度[L,R],后来的海报会覆盖前面来的海报,问最后从最上面看,能看得到几种海报
我的代码C++提交阔以AC,但是G++就会T,搜了一下G++与C++的区别:
https://blog.csdn.net/dt2131/article/details/58689903
这道题poj上的数据有点弱,贴一个讨论里很火的三组数据:
input:
3
3
5 6
4 5
6 8
3
1 10
1 3
6 10
5
1 4
2 6
8 10
3 4
7 10
output:
2
3
4
这道题关键就是离散化,<mark>而给的区间是格子,而不是点</mark>
比如图上的:
给的区间是
2
1 5
6 10
离散化后应该为
2
1 1
2 2
他们有的是在中间差值大于1的地方加点,但是我不喜欢这种T_T
我是先把格子弄成点然后再映射,右端点+1就是这段区间的右边比如上面这个例子弄了之后就只有 1 6 11 三个点,就是两段了
//#include"bits/stdc++.h"
#include"iostream"
#include"map"
#include"algorithm"
#include"vector"
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;
int tree[maxn];
int N,n;
map<int,int>Mp,ans;
pair<int,int>a[maxn],b[maxn];
vector<int>vec;
void Build(int id,int L,int R)
{
tree[id]=-1;//-1表示没有颜色
if(L==R)return ;
int mid=L+R>>1;
Build(id<<1,L,mid);
Build(id<<1|1,mid+1,R);
}
void pushdown(int id)//把颜色传给子区间,并把这个节点的颜色改成0,表示有多种颜色
{
if(tree[id])tree[id<<1]=tree[id<<1|1]=tree[id];
tree[id]=0;//0代表有很多种颜色
}
void Change(int id,int L,int R,int qL,int qR,int x)
{
if(qL>R||qR<L)return ;//超过了需要查询的区间就直接退出
if(qL<=L&&qR>=R)
{
tree[id]=x;
return ;
}
pushdown(id);//更新当前节点的值
int mid=L+R>>1;
Change(id<<1 ,L ,mid,qL,qR,x);
Change(id<<1|1,mid+1, R,qL,qR,x);
}
void solve(int id,int L,int R)
{
if(tree[id]==-1)return ;//没有颜色
if(tree[id])//如果不是0,那说明只有一种这个区间只有一种颜色
{
ans[tree[id]]=1;
return ;
}
if(L==R)
{
if(tree[id])ans[tree[id]]=1;
return ;
}
int mid=L+R>>1;
solve(id<<1,L,mid);
solve(id<<1|1,mid+1,R);
}
void print()//输出离散化后的端点以及离散化后的区间
{
cout<<"vec :\n";
for(int i=0;i<vec.size();i++)cout<<vec[i]<<" ";
cout<<endl;
cout<<"distinct:\n";
for(int i=1;i<=N;i++)cout<<a[i].first<<" "<<a[i].second<<endl;
cout<<endl;
}
void printTree()//输出线段树
{
cout<<"tree :"<<endl;
for(int i=1;i<=(n-1)*4;i++)
{
cout<<"id="<<i<<" tree="<<tree[i]<<" | ";
if((i&(i+1))==0)cout<<endl;
}
cout<<endl;
}
int main()
{
int T;
cin>>T;
while(T--)
{
ans.clear();
Mp.clear();
vec.clear();
cin>>N;
for(int i=1;i<=N;i++)
{
cin>>b[i].first>>b[i].second;//这道题给的区间不是点区间,而是格子区间
Mp[b[i].first]=1;//用Mp记录一哈哪些点是出现过的,方便之后离散化
Mp[b[i].second+1]=1;//右端点+1
}
for(map<int,int>::iterator it=Mp.begin();it!=Mp.end();it++)vec.push_back(it->first);//存储离散化后的点
sort(vec.begin(),vec.end());//把原来的点排序
n=vec.size();//离散化后的点
for(int i=0;i<n;i++)Mp[vec[i]]=i+1;//对原来的点进行离散化
for(int i=1;i<=N;i++)
{
a[i].first=Mp[b[i].first];
a[i].second=Mp[b[i].second+1]-1;//注意是找+1后的右端点的映射的值的前一个点
}
//print();
Build(1,1,n);
for(int i=1;i<=N;i++)Change(1,1,n,a[i].first,a[i].second,i);
solve(1,1,n);
cout<<ans.size()<<endl;
}
}