20240202-训练赛随记

机场检录

//二分
#include <bits/stdc++.h>
using namespace std;
long long n,m,a[100005];
bool check(long long x){
    long long t=0;
    for(int i=1;i<=n;i++) t+=(x/a[i]);
    return t>=m;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin >> a[i];
    long long l=0,r=1e13;
    while(l<r){
        long long mid=(l+r)>>1;
        if(!check(mid)) l=mid+1;
        else r=mid;
    }
    cout<<r;
    return 0;
}

录制比赛

usaco银
dp,贪心?
按 开始时间/结束时间 排序?
#include <bits/stdc++.h>
using namespace std;
struct node{
	int l,r;
}a[205];
bool cmp(node a,node b){
	if(a.r==b.r) return a.l>b.l;
	return a.r<b.r;
}
int n,s1,s2,cnt;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i].l>>a[i].r;
	sort(a+1,a+n+1,cmp); 
	for(int i=1;i<=n;i++){
		if(s1<=a[i].l){
			cnt++;
			s1=a[i].r;
		}
		else if(s2<=a[i].l){
			cnt++;
			s2=a[i].r;
			swap(s1,s2);
		}
	}
	cout<<cnt;
	return 0;
}

水果

60分 刷表法 
for(int j=i+1;j<=i+v[i];j++) d[j]=min(d[j],d[i]+c[i]);
标记永久化 区间更新

填表法 倒填
区间查询 单点更新
a[i]=que(max(i-r[i],0),i-1,1)+v[i];
add(i,1,a[i]);
1.刷表法
用当前天的最优解,更新后面的日期。线段树区间更新,单点求值。
2. 填表法
倒着来,dp[i]表示的从i到n的最小花费。如果要买当前水果,就需要在[i+1,n]这些天里,选择一个最小的dp值即可。
3.树状数组
刷表法中的线段树,可以用树状数组代替。因为前面的天数已经没有用了。更新[L,R]与更新[1,R]一样。
树状数组,更新前缀,查询单点。
4.暴力
还有一种暴力优化,基于刷表法的更新区间[L,R] 从R到L扫描,如果无法更新了,就break。正确性比较显然,但是还是可以通过特意构造数据,让区间跑满。
#include <bits/stdc++.h>
using namespace std;
int n,m,a[50005],b[50005],d[50005];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        d[i]=d[i-1]+a[i];
    }
    for(int i=1;i<=n;i++) cin>>b[i];
    for(int i=1;i<=n;i++){
        for(int j=min(n,i+b[i]-1);j>=i&&d[i-1]+a[i]<d[j];j--){
            d[j]=d[i-1]+a[i];
        }
    }
    cout<<d[n];
    return 0;
}
posted @ 2024-02-03 09:37  Firepaw喵喵喵  阅读(17)  评论(0)    收藏  举报