//線段樹的染色類型題目<br />//這題通過逆序修改線段樹可以簡單的實現,這是一種比較巧妙地做法<br />//也可以通過記錄左顏色和右顏色來維護線段樹實現<br />//下面的代碼是通過逆序覆蓋來實現的,逆序覆蓋,即將最後一次貼上去的海報優先處理<br />//這樣的話可以省去很多按順序插入處理步驟,但是無法實現動態詢問<br />//在離散化的時候我一開始使用MAP來實現,結果800MS,差點爆掉,實踐證明MAP的查詢速度是很慢的,還不如寫個二分搞定<br />//但下面的代碼嚴格來說是錯誤的,離散化有問題,不過資料太弱,還是可以AC的<br />#include<iostream><br />#include<algorithm><br />#include<vector><br />#define MAX 10005<br />using namespace std;<br />struct seg<br />{<br />int l,r,color,cover;<br />}segTree[8 * MAX];//4 是線段樹特徵,2是10000次邊最壞有20000個不同邊界,所以要*8<br />struct Extent//區間的結構體<br />{<br />int x,y;<br />}extent[MAX];<br />bool vis[2 * MAX];<br />int M[2 * MAX];<br />int ans,N;<br />void buildTree(int fa,int l,int r)//建樹<br />{<br />segTree[fa].l = l;<br />segTree[fa].r = r;<br />segTree[fa].color = segTree[fa].cover = 0;<br />if(l == r)return;<br />int mid = (segTree[fa].l + segTree[fa].r) >> 1;<br />if(r <= mid)buildTree(2*fa,l,r);<br />else if(l > mid)buildTree(2*fa+1,l,r);<br />else<br />{<br />buildTree(2*fa,l,mid);<br />buildTree(2*fa+1,mid+1,r);<br />}<br />}<br />int getIndex(int data)//通過二分尋找返回離散後的數組下標<br />{<br />int mid,x = 1,y = N+1;<br />while(x < y)<br />{<br />mid = x + (y - x) / 2;//確保分界點總是靠近區間起點<br />if(M[mid] == data)return mid;<br />else if(M[mid] > data)y = mid;<br />else x = mid + 1;<br />}<br />return -1;<br />}<br />void insert(int fa,int l,int r,int color)<br />{<br />if(segTree[fa].cover > 0)return;//逆序覆蓋,所以如果該區間已被覆蓋過了,就直接返回即可,因為前面的覆蓋對結果沒有影響<br />if(l == segTree[fa].l && r == segTree[fa].r)<br />{<br />if(segTree[fa].cover == 0)<br />{<br />segTree[fa].color = color;//染色<br />segTree[fa].cover = 1;<br />if(!vis[color])//如果這種顏色沒出現過<br />{<br />++ans;<br />vis[color] = 1;<br />}<br />}<br />return;<br />}<br />int mid = (segTree[fa].l + segTree[fa].r) >> 1;<br />if(r <= mid)insert(2*fa,l,r,color);<br />else if(l > mid)insert(2*fa+1,l,r,color);<br />else<br />{<br />insert(2*fa,l,mid,color);<br />insert(2*fa+1,mid+1,r,color);<br />}<br />if(segTree[2*fa].cover > 0 && segTree[2*fa+1].cover > 0)//通過回溯跟結點順便維護區間的覆蓋情況<br />segTree[fa].cover = 1;<br />}<br />int main()<br />{<br />//freopen("in.txt","r",stdin);<br />int t,n,x,y;<br />scanf("%d",&t);<br />while(t--)<br />{<br />N = 0;<br />int color = 0;<br />scanf("%d",&n);<br />vector<int> v;<br />memset(vis,0,sizeof(vis));<br />ans = 0;<br />for(int i = 0;i < n;++i)<br />{<br />scanf("%d%d",&extent[i].x,&extent[i].y);<br />v.push_back(extent[i].x);<br />v.push_back(extent[i].y);<br />}<br />sort(v.begin(),v.end());<br />//離散化過程<br />M[++N] = v[0];<br />for(int i = 1;i < v.size();++i)<br />if(v[i] != v[i-1])<br />M[++N] = v[i];<br />buildTree(1,1,N);<br />for(int i = n - 1;i >= 0;--i)<br />{<br />x = getIndex(extent[i].x);<br />y = getIndex(extent[i].y);<br />insert(1,x,y,++color);//對每條邊插入不同的顏色<br />}<br />printf("%d/n",ans);<br />}<br />return 0;<br />}