1. 程式人生 > >Openjudge NOI題庫2.4基本演算法之分治 7620:區間合併

Openjudge NOI題庫2.4基本演算法之分治 7620:區間合併

 總時間限制: 1000ms 記憶體限制: 65536kB
描述

給定 n 個閉區間 [ai; bi],其中i=1,2,...,n。任意兩個相鄰或相交的閉區間可以合併為一個閉區間。例如,[1;2] 和 [2;3] 可以合併為 [1;3],[1;3] 和 [2;4] 可以合併為 [1;4],但是[1;2] 和 [3;4] 不可以合併。

我們的任務是判斷這些區間是否可以最終合併為一個閉區間,如果可以,將這個閉區間輸出,否則輸出no。

輸入
第一行為一個整數n,3 ≤ n ≤ 50000。表示輸入區間的數量。
之後n行,在第i行上(1 ≤ i ≤ n),為兩個整數 ai 和 bi ,整數之間用一個空格分隔,表示區間 [ai; bi](其中 1 ≤ ai ≤ bi ≤ 10000)。
輸出
輸出一行,如果這些區間最終可以合併為一個閉區間,輸出這個閉區間的左右邊界,用單個空格隔開;否則輸出 no。
樣例輸入
5
5 6
1 5
10 10
6 9
8 10
樣例輸出
1 10
思路:資料的儲存肯定選擇結構體陣列了,因為方便遍歷嗎,然後儲存的時候,它輸入不一定前面大後面小,所以在輸入的時候我就先把區間左右大小分好存進結構體,前面輸入資料部分程式碼能看懂 就不多說了,z是左,y是右,qq是我定義的qj(區間)型別的陣列,然後比較部分,就像我們看這個區間是否能合併一樣,先按區間(按照左界,左界相等看右界)排序,像(1,3)(2,4)這種情況是最好做的,只需要看相鄰左右界限,但是對於(1,8)(2,7),要是隻看相鄰左右就不行了,8比2大是沒錯,可能得出來的結果是(1,7),這種情況對於如果一開始記錄左界最大和右界最小值還是好計算的,但是對於(1,9)(2,4),(6,8)就會判斷錯誤,所以在比較過程中我們要找右界最大的,讓它跟左界一直比較,左界可以比他小,但是不能比他大,一旦比他大就直接輸出no並且返回0。這就是為啥一定要有
qq[1].y=max(qq[1].y,qq[i].y);
思路清晰了程式碼就好看了,沒加太多註釋
#include <stdio.h>
#include<iostream> 
#include<algorithm>
using namespace std;
struct qj{//區間 結構體 
	int z,y;//左 右 
};
qj qq[50000];
int zz=50000,yy=-50000;
int cmp(qj &a,qj &b)
{
       if(a.z<b.z)return 1;//左界小返回1 
    if(a.z>b.z)return 0;//左界大返回0
    else 
      {
          if(a.y<b.y)return 1;//左界相同返回右界小的 
          else return 0;
      }
}
int main()
{
    int n,x1,x2,t;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    	cin>>x1>>x2;
    	if(x1<x2)
    	{
    		t=x1;x1=x2;x2=t; 
		}
    	qq[i].y=x1;
    	qq[i].z=x2;//使得左界永遠小於等於左界 
    	if(qq[i].z<=zz)zz=qq[i].z;
    	if(qq[i].y>=yy)yy=qq[i].y;
	}
	sort(qq+1,qq+n+1,cmp);//對區間排序 
	for(int i=2;i<=n;i++)
	{
       if(qq[1].y<qq[i].z) //如果左界大於右界 返回 
		{
			cout<<"no";
			return 0;
		} 
		else qq[1].y=max(qq[1].y,qq[i].y);
	}
	cout<<zz<<" "<<yy;//輸出該輸入的區間中左界最小和右界最大 
	return 0;
}