作業H4-1/2/數據

1.擺放垃圾桶

題目描述

濱海公園旁邊新鋪了一條路,把這條路分成n段,依次編號爲1…n。爲了防止遊客把垃圾扔到海里,war要在路上放一些垃圾桶🚮。政府提出了m個要求,每個要求包含三個整數l,r,k,表示路段l到r之間至少有k個垃圾桶 。垃圾桶放太多不僅浪費資源,也影響風景,所以每個路段至多可以放一個垃圾桶。爲了環保♻️,war最少要放多少個垃圾桶才能滿足要求?

輸入描述

第一行爲n(1≤n≤3*10^4)(1n3104),表示路段數。

第二行爲m(1≤m≤5000)(1m5000),表示要求數。

下面m行,每行描述一條建議l,r,k,用一個空格分隔,(1≤l≤r≤3*10^4,k≤r-l+1)(1lr3104,krl+1)。

輸出描述

輸出只有一個數,爲滿足政府所有的要求,需要的垃圾桶的最少數量。

/*
    按照區間右端點從小到大排序
    對於每個要求,先遍歷一遍所在區間,來確定已有的垃圾桶數
    然後計算一下還需要額外的垃圾桶數,從區間的最右邊依次向左填入垃圾桶,複雜度爲O(n*m)
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 30010
using namespace std;
int n,m;
struct node{
    int l,r,k;
    bool operator < (const node u)const {
        if(r!=u.r)return r<u.r;
        else return l>u.l;
    }
}p[maxn];
bool a[maxn];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].k);
    }
    sort(p+1,p+m+1);
    for(int i=1;i<=m;i++){
        int cnt=0;
        for(int j=p[i].l;j<=p[i].r;j++)cnt+=a[j];
        cnt=p[i].k-cnt;
        for(int j=p[i].r;j>=p[i].l;j--){
            if(cnt<=0)break;
            if(!a[j])a[j]=1,cnt--;
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
        ans+=a[i];
    printf("%d\n",ans);
    return 0;
}

 

2.看電影

題目描述

終於可以隨意出入校園啦!於是,n個人決定去看電影🎬。每個人都要先去A影院再去B影院。第i個人在A,BAB影院的觀影時間分別爲a_i,b_iai,bi。按照疫情防控要求,每個影院最多允許1人同時觀影。那麼怎樣安排這n個人的觀影順序,能使所有人都在A,BA,B影院觀影完的總時間最少。

輸入描述

第一行爲n(0<n<1000)(0<n<1000),表示人數。

第二行n個數,第i個數爲a_i(1≤a_i≤350)ai(1ai350),中間有空格。

第三行n個數,第i個數爲b_i(1≤b_i≤350)bi(1bi350),中間有空格。

輸出描述

輸出只有一個數,爲最少的總時間。

/*
    流水作業調度問題:
    最優調度: 讓M1沒有空閒, M2的空閒時間儘量短。
    設S1 爲 a < b的作業集合,S2爲 a >= b 的作業集合,將S1的作業按a 遞增序排序,S2 中的作業按照b 遞減序排序,則最優順序爲 S1(排序後) + S2(排序後)
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 1010
using namespace std;
struct node {
    int x,y,end;
}a[maxn],b[maxn];
bool cmp1(node u,node v){
    return u.x<v.x;
}
bool cmp2(node u,node v){
    return u.y>v.y;
}
int n,cnt1,cnt2;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i].x);
    for(int i=1;i<=n;i++)scanf("%d",&a[i].y);
    for(int i=1;i<=n;i++)
        if(a[i].x<a[i].y)b[++cnt1]=a[i];
    cnt2=cnt1;
    for(int i=1;i<=n;i++)
        if(a[i].x>=a[i].y)b[++cnt2]=a[i];
    sort(b+1,b+cnt1+1,cmp1);
    sort(b+cnt1+1,b+cnt2+1,cmp2);

    for(int i=1;i<=n;i++){
        b[i].end=b[i-1].end+b[i].x;
    }
    int b_end=0,time=b[1].x;
    for(int i=1;i<=n;i++){
        b_end=max(b[i].end,b_end)+b[i].y;
    }
    printf("%d\n",b_end);
    return 0;
}

 

 

 

3.劃分石頭

題目描述

海邊有很多好看的石頭🪨,war把它們收集起來依次排成一排,一共n個,第i個石頭的重量爲w_iwi。他想將其分成m段,每一段連續,並且重量和最大的段的和最小。請你幫幫他~

輸入描述

第一行爲n(1≤n≤10^5)(1n105),m(m≤n)(mn)。

第二行n個數,第i個數爲w_i(0≤wi≤10^9)wi(0wi109),中間有空格。

輸出描述

輸出只有一個數,重量和最大的段的和。

/*
    二分答案,二分一個最大的重量和
    每次檢驗答案時依次選取石頭,直到重量和超過最大的重量和,就重新選取
    檢驗一下一共選取的段數是否大於m即可
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
using namespace std;
int n,m;
long long a[maxn];

bool check(long long x){
    int y=1;
    long long sum=0;
    for(int i=1;i<=n;i++){
        if(sum+a[i]>x){
            sum=a[i];
            y++;
        }
        else sum+=a[i];
    }
    if(y>m)return 0;
    else return 1;
}

int main(){
    scanf("%d%d",&n,&m);
    long long ans,l=0,r=0;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        r+=a[i];
        l=max(l,a[i]);
    }
    while(l<=r){
        long long mid=(l+r)>>1;
        if(check(mid)){
            r=mid-1;
            ans=mid;
        }
        else l=mid+1;
    }
    printf("%lld\n",ans);return 0;
}

 

 

4.撿貝殼

題目描述

war發現海邊還有好看的貝殼🐚,他把n個貝殼依次排成一排,第i個貝殼的體積爲v_ivi。war覺得平均體積最大,且長度不小於m的一段貝殼最好看。請你幫他找出這一段~

輸入描述

第一行爲n(1≤n≤10^5)(1n105),m(m≤n)(mn)。

第二行n個數,第i個數爲v_i(0≤vi≤2000)vi(0vi2000),中間有空格。

輸出描述

輸出一個整數,表示這個平均體積的1000倍。不用四捨五入,直接輸出。

/*
    二分答案,檢驗答案時,將每個數字都減去平均數,然後求一個前綴和
    mn[i]存儲前i個前綴和的最小值, mx[i]存儲後i個前綴和的最大值
    那麼檢查mx[i+m]-mn[i]的最大值是否大於零即可
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
using namespace std;
int n,m;
double a[maxn],sum[maxn];
double mn[maxn],mx[maxn];
bool check(double mid){
    mn[0]=2000;
    for(int i=1;i<=n;i++){
        sum[i]=sum[i-1]+a[i]-mid;
        mn[i]=min(mn[i-1],sum[i]);
    }
    mx[n+1]=-0x7fffffff;
    for(int i=n;i>=1;i--){
        mx[i]=max(mx[i+1],sum[i]);
    }
    double res=-0X7fffffff;
    mn[0]=0;
    for(int i=0;i<=n-m;i++){
        res=max(res,mx[i+m]-mn[i]);
    }
    return res>=0;
}
int main(){
    scanf("%d%d",&n,&m);
    double ans=0;
    double l=2000,r=0;
    for(int i=1;i<=n;i++){
        scanf("%lf",&a[i]);
        l=min(l,a[i]);
        r=max(r,a[i]);
    }
    ans=l;
    while(r-l>0.00001){
        double mid=(l+r)/2.0;
        if(mid>5){
            int u=0;
        }
        if(check(mid)){
            ans=mid;
            l=mid;
        }
        else r=mid;
    }
    int w=r*1000;
    printf("%d\n",w);
    return 0;
}

 

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