1. 程式人生 > >HihoCoder 1590 : 緊張的會議室(區間最大+離散化)

HihoCoder 1590 : 緊張的會議室(區間最大+離散化)

會議室 0ms clu can 限制 兩個 closed algorithm ret

時間限制:20000ms 單點時限:2000ms 內存限制:256MB

描述

小Hi的公司最近員工增長迅速,同時大大小小的會議也越來越多;導致公司內的M間會議室非常緊張。

現在小Hi知道公司目前有N個會議,其中第i個會議的時間區間是(Si, Ei)。 註意這裏時間區間可以視為是開區間,也就是說(3, 5)和(5, 6)不會被視為是同時進行的會議。

小Hi想知道如果他新增一個會議,時間區間是(X, Y),會不會導致出現會議室不夠用的情況?

已知目前的N個會議不會導致會議室不夠用。

輸入

第一行包含兩個整數:N和M。

以下N行每行兩個整數Si和Ei,代表一個會議的時間區間。

之後一行包含一個整數Q,代表小Hi詢問的次數。

以下Q行每行包含兩個整數Xi和Yi,表示小Hi希望新增的會議時間。

對於30%的數據,1 <= N, M, Q <= 1000

對於100%的數據,1 <= N, M, Q <= 100000 0 <= Si < Ei <= 100000000 0 <= Xi < Yi <= 100000000

輸出

對於每一次詢問,輸出YES或者NO。YES代表會議室夠用,NO代表會議室不夠用。

樣例輸入
3 1  
1 2  
3 4  
5 6  
2  
2 3  
2 4
樣例輸出
YES  
NO

思路: 前綴和性質,[x,y]覆蓋,則sum[x]++,sum[y+1]--,正好題目給定的是左開右閉[x,y),則直接離散化,求區間最大。

開始用樹狀數組,一直超時。後來改成倍增就ok了。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1000010;
int
x[maxn],y[maxn],s[maxn],e[maxn],sum[maxn],q[maxn]; int tmp,tmp2,cnt,R[maxn],dp[maxn][20]; int max(int a,int b){ if(a>b) return a; return b;} int read() { int res=0; char c=getchar(); while(c>9||c<0) c=getchar(); while(c>=0&&c<=9){res=res*10+c-0; c=getchar(); } return res; } int RMQ() { for(int i=1;i<=cnt;i++) dp[i][0]=sum[i]; for(int i=1;i<20;i++) for(int j=1;j+(1<<i)<cnt;j++) dp[j][i]=max(dp[j][i-1],dp[j+(1<<(i-1))][i-1]); } int query(int l,int r) { int k=log2(r-l+1); return max(dp[l][k],dp[r-(1<<k)+1][k]); } int main() { int N,M,Q,i,j,Max=0; scanf("%d%d",&N,&M); for(i=1;i<=N;i++){ scanf("%d%d",&s[i],&e[i]); s[i]++; e[i]++; q[++cnt]=s[i]; q[++cnt]=e[i]; } scanf("%d",&Q); for(i=1;i<=Q;i++){ scanf("%d%d",&x[i],&y[i]); x[i]++; y[i]++; q[++cnt]=x[i]; q[++cnt]=y[i]; } sort(q+1,q+cnt+1); unique(q+1,q+cnt+1); for(i=1;i<=N;i++){ tmp=lower_bound(q+1,q+cnt+1,s[i])-q; sum[tmp]++; tmp=lower_bound(q+1,q+cnt+1,e[i])-q; sum[tmp]--; } for(i=1;i<=cnt;i++) { sum[i]+=sum[i-1]; Max=max(Max,sum[i]); } RMQ(); for(i=1;i<=Q;i++){ tmp=lower_bound(q+1,q+cnt+1,x[i])-q; tmp2=lower_bound(q+1,q+cnt+1,y[i])-q; if(query(tmp,tmp2-1)<M) printf("YES\n"); else printf("NO\n"); } return 0; }

超時代碼:

技術分享圖片
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=5000010;
int x[maxn],y[maxn],s[maxn],e[maxn],sum[maxn],q[maxn];
int tmp,tmp2,cnt,R[maxn];
int max(int a,int b){ if(a>b) return a; return b;}
int read()
{
    int res=0; char c=getchar();
    while(c>9||c<0) c=getchar();
    while(c>=0&&c<=9){res=res*10+c-0; c=getchar(); } 
    return res;
}
void add(int i,int val)
{
    while(i<=cnt){
        R[i]=max(R[i],val);
        i+=(-i)&i;
    }
}
int query(int l,int r)
{
    int res=0;
    while(l<=r&&r){
        while(r-(-r)&r>=l&&r) {
            res=max(res,R[r]);
            r-=(-r)&r;
        }
        if(r>=l) res=max(res,sum[r--]);
    } return res;
}
int main()
{
    int N,M,Q,i,j,Max=0;
    scanf("%d%d",&N,&M);
    for(i=1;i<=N;i++){
        scanf("%d%d",&s[i],&e[i]);
        s[i]++; e[i]++;
        q[++cnt]=s[i]; 
        q[++cnt]=e[i];
    }
    scanf("%d",&Q);
    for(i=1;i<=Q;i++){
        scanf("%d%d",&x[i],&y[i]);
        x[i]++;  y[i]++;
        q[++cnt]=x[i];
        q[++cnt]=y[i];
    }
    sort(q+1,q+cnt+1);
    unique(q+1,q+cnt+1);
    for(i=1;i<=N;i++){
        tmp=lower_bound(q+1,q+cnt+1,s[i])-q; sum[tmp]++; 
        tmp=lower_bound(q+1,q+cnt+1,e[i])-q; sum[tmp]--;
    }
    for(i=1;i<=cnt;i++) {
         sum[i]+=sum[i-1];
         add(i,sum[i]);
         Max=max(Max,sum[i]);
    }
    for(i=1;i<=Q;i++){
        if(Max>M) printf("NO\n");
        else {
            tmp=lower_bound(q+1,q+cnt+1,x[i])-q;
            tmp2=lower_bound(q+1,q+cnt+1,y[i])-q;
            if(query(tmp,tmp2-1)<M) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}
View Code

HihoCoder 1590 : 緊張的會議室(區間最大+離散化)