AtCoderBeginnerContest128 DEF

ABC128比赛的D、E、F题详解。D题可通过暴力解决,双循环确定最优珠宝持有。E题是贪心策略结合STL,根据障碍物和人的出发时间优化路径。F题详情见外部链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AtCoder Beginner Contest 128 DEF

https://atcoder.jp/contests/abc128

D题
题意:
v数组长度是n,代表有n个珠宝,可以进行k次操作;
每次操作,可以选择
1 从左边拿一个到手里
2 或者从右边拿一个手里
3 或者从手里放回一个到左边
4 或者从手里放回一个到右边
问最后手里所拥有珠宝价值总和最大
在这里插入图片描述
在这里插入图片描述
思路:
还以为是什么复杂的dp,但其实暴力就可以。
按照贡献来想
两重暴力循环,从左边拿几个,从右边拿几个,如果k次操作有剩,则将手里小于0的珠宝放回去。

int t,n,m;
int a[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	ll res = 0;
	for(int i=0;i<=n;i++){
		for(int j=0;i+j<=n;j++){
			if(i + j > m) continue;
			int k = m - i - j;
			ll tmp = 0;
			priority_queue<int,vector<int>,greater<int>> q;
			for(int op=1;op<=i;op++) q.push(a[op]),tmp+=a[op];
			for(int op=n;op>n-j;op--) q.push(a[op]),tmp+=a[op];
			while(q.size() && q.top() < 0 && k>0){
				tmp -= q.top();
				k--;
				q.pop();
			} 
			res = max(res,tmp);
		}
	}
	printf("%lld\n", res);
	return 0;
}

E题 贪心,stl,思维
题意:
数轴上,n个障碍物,
第i个障碍物,在[Si,Ti)这个时间段存在于数轴的Xi点上
Q个人,一开始都在数轴的0点上
Di代表这个人在Di秒向数轴正半轴出发,速度1秒1格
问每个人最远可以走到哪,如果可以走无限远则输出-1。
在这里插入图片描述
思路:
因为速度是1秒1格,所以时间和距离有相对关系。
每个障碍物都有对应在0点上的[Si,Ti)即从0点在这个时间段出发正好和障碍物时间段对应。
用set存每个人的出发时间。
按照障碍物的Xi,排序,因为距离近的先碰到。
每次lower_bound查找在这个时间段的人,然后标记被这个障碍物阻挡。
每次标记完只会,从set中erase掉。

int t,n,m,q;
struct node{
    int s,t,x;
    bool operator<(const node &no)const{
        return x < no.x;
    }
}bo[N];
int res[N];
map<int,int> pos;
set<int> se;
vector<int> tmp;
int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        bo[i].s = max(a-c,0);
        bo[i].t = max(b-c,0);
        bo[i].x = c;
    }
    sort(bo+1,bo+1+n);
    for(int i=1;i<=q;i++){
        int x;
        scanf("%d",&x);
        se.insert(x);
        pos[x] = i;
    }
    memset(res,-1,sizeof res);
    for(int i=1;i<=n;i++){
        auto l = se.lower_bound(bo[i].s);
        auto r = se.lower_bound(bo[i].t);
        for(auto j = l ; j != r; j++){
            res[pos[*j]] = bo[i].x;
            tmp.push_back(*j);
        }
        for(auto t : tmp) se.erase(t);
        tmp.clear();
    }
    for(int i=1;i<=q;i++){
        printf("%d\n", res[i]);
    }
    return 0;
}

F题
转载自:https://www.cnblogs.com/Dup4/p/10929996.html
在这里插入图片描述
太妙了,具体的解释,注释里解释下。

ll t,n,m;
ll s[N];
int vis[N];

int main(){
	scanf("%lld",&n);
	for(int i=0;i<n;i++) scanf("%lld",&s[i]);
	ll res = 0;
	//C = A - B 如果A <= B ,就会跳到<=0,所以从1开始
	for(int C = 1;C <= n;C ++){
		ll tmp = 0;
		for(int k=1;1ll * k * C < n;k++){// k * C < n
			ll a = k * C;//增加的第一个点
			ll b = n - 1 - k * C;//增加的第二个点
			//由公式A+KC = N - 1反推A,由C = A - B反推B
			ll A = b,B = b - C;
			if(A <= 0 || B <= 0) break;//题目说了A,B是正整数
			//如果跳出范围或者重复了
			if(a < 0 || a >= n || b < 0 || b >= n || a == b) break;
			//如果在当前这层重复了。(这样就不用每次memset)
			if(vis[a] == C || vis[a] == C){
				break;
			}
			vis[a] = C;
			vis[b] = C;
			tmp += s[a];
			tmp += s[b];
			res = max(res,tmp);
		}
	}
	printf("%lld\n", res);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值