作业H4-1/2/数据
1.摆放垃圾桶
题目描述
滨海公园旁边新铺了一条路,把这条路分成n段,依次编号为1…n。为了防止游客把垃圾扔到海里,war要在路上放一些垃圾桶🚮。政府提出了m个要求,每个要求包含三个整数l,r,k,表示路段l到r之间至少有k个垃圾桶 。垃圾桶放太多不仅浪费资源,也影响风景,所以每个路段至多可以放一个垃圾桶。为了环保♻️,war最少要放多少个垃圾桶才能满足要求?
输入描述
第一行为n(1≤n≤3*10^4)(1≤n≤3∗104),表示路段数。
第二行为m(1≤m≤5000)(1≤m≤5000),表示要求数。
下面m行,每行描述一条建议l,r,k,用一个空格分隔,(1≤l≤r≤3*10^4,k≤r-l+1)(1≤l≤r≤3∗104,k≤r−l+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,BA,B影院的观影时间分别为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(1≤ai≤350),中间有空格。
第三行n个数,第i个数为b_i(1≤b_i≤350)bi(1≤bi≤350),中间有空格。
输出描述
输出只有一个数,为最少的总时间。
/* 流水作业调度问题: 最优调度: 让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)(1≤n≤105),m(m≤n)(m≤n)。
第二行n个数,第i个数为w_i(0≤wi≤10^9)wi(0≤wi≤109),中间有空格。
输出描述
输出只有一个数,重量和最大的段的和。
/* 二分答案,二分一个最大的重量和 每次检验答案时依次选取石头,直到重量和超过最大的重量和,就重新选取 检验一下一共选取的段数是否大于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)(1≤n≤105),m(m≤n)(m≤n)。
第二行n个数,第i个数为v_i(0≤vi≤2000)vi(0≤vi≤2000),中间有空格。
输出描述
输出一个整数,表示这个平均体积的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; }