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