2017大學生程序設計邀請賽(華東師範大學)F. 麗娃河的狼人傳說

傳送門:http://acm.ecnu.edu.cn/contest/11/problem/F/

麗娃河是華師大著名的風景線。但由於學校財政緊缺,麗娃河邊的路燈年久失修,一到晚上就會出現走在河邊要打着手電的情況,不僅非常不方便,而且影響安全:已經發生了大大小小的事故多起。

方便起見,麗娃河可以看成是從 1  n  的一條數軸。爲了美觀,路燈只能安裝在整數點上,每個整數點只能安裝一盞路燈。經專業勘測,有 m  個區間特別容易發生事故,所以至少要安裝一定數量的路燈,

請問至少還要安裝多少路燈。

Input

第一行一個整數 T (1T300) ,表示測試數據組數。

對於每組數據:

  • 第一行三個整數 n,m,k (1n10 3 ,1m10 3 ,1kn) 

  • 第二行 k  個不同的整數用空格隔開,表示這些位置一開始就有路燈。

  • 接下來 m  行表示約束條件。第 i  行三個整數 l i ,r i ,t i   表示:第 i  個區間 [l i ,r i ]  至少要安裝 t i   盞路燈 (1l i r i n,1t i n) 

Output

對於每組數據,輸出 Case x: y。其中 x 表示測試數據編號(從 1 開始),y 表示至少要安裝的路燈數目。如果無解,y 爲1 

Examples

Input
3
5 1 3
1 3 5
2 3 2
5 2 3
1 3 5
2 3 2
3 5 3
5 2 3
1 3 5
2 3 2
4 5 1
Output
Case 1: 1
Case 2: 2
Case 3: 1

Note

因爲今天不是滿月,所以狼人沒有出現。

題解:

按右端點排序,然後對於不滿足條件的儘量往右壘就好了。貪心的證明:由於左邊的都已經壘滿了,所以壘左邊的肯定是沒意義的。壘中間肯定沒有壘右邊的號,因爲右邊的區間不可能長得斷開,使得壘在左邊收益更大。這樣就可以實現O(n 2 ) 

本題雖然不作要求,但是可以做到 O(nlog 2 n) ,用線段樹維護,不符合條件可能需要二分。具體細節留給讀者思考。

模仿Q巨AC代碼

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1005;
int usd[MAXN],l[MAXN],r[MAXN],t[MAXN],id[MAXN];
int main()
{
    int T;
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        memset(usd,0,sizeof(usd));
        for(int i=1;i<=k;i++)
        {
            int x;
            scanf("%d",&x);
            usd[x]=1;
        }
        int gg=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&l[i],&r[i],&t[i]),id[i]=i;
            gg|=(t[i]>r[i]-l[i]+1);
            for(int j=1;j<=n;j++)
                t[i]-=(l[i]<=j && j<=r[i] && usd[j]);
        }
        if(gg)
        {
            printf("Case %d: %d\n",ca,-1);
            continue;
        }
        sort(id+1,id+m+1,[](int a,int b){return r[a]<r[b];});
        int res=0;
        for(int ii=1;ii<=m;ii++)
        {
            int i=id[ii];
            for(int j=r[i],k=t[i];k>0;j--)
            {
                if(usd[j])continue;
                for(int s=1;s<=m;s++)
                    t[s]-=(l[s]<=j && j<=r[s]);
                usd[j]=1,k--,res++;
            }
        }
        printf("Case %d: %d\n",ca,res);
    }
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章