作业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;
}

 

posted @ 2021-03-25 17:07  Echo宝贝儿  阅读(41)  评论(0编辑  收藏  举报