poj 2528 Mayor's posters【區間離散化】
阿新 • • 發佈:2018-12-22
文章目錄
題目連結:
http://poj.org/problem?id=2528
題意:就是有 N 種海報,每種海報有個長度[L,R],後來的海報會覆蓋前面來的海報,問最後從最上面看,能看得到幾種海報
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
這道題關鍵就是離散化,而給的區間是格子,而不是點
比如圖上的:
給的區間是
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;
}
}