1. 程式人生 > >poj 2528 Mayor's posters【區間離散化】

poj 2528 Mayor's posters【區間離散化】

文章目錄

題目連結:

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

這道題關鍵就是離散化,而給的區間是格子,而不是點
在這裡插入圖片描述
比如圖上的:
給的區間是
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; } }