AtCoder Beginner Contest 188 D - Snuke Prime

题目链接:传送门
思路:本来想的是直接给区间排序,后来发现太麻烦了,直接对每个点(一个区间有两个点)的贡献左区间计+c[i] , 负区间计-c[i] ,进行排序即可,每次访问下一个点的时候,首先计算i - 1 与 i 点之间的花费(此处与C进行比较,保证每天最多花C),把上一个点的贡献c[i - 1]计入新的c[i]。
做到这里,本题还有一个关键点:若一个区间为[l , r],l点的贡献从它自己l位置开始起效,而r点从r + 1点才开始起效,因此记录点的贡献时,右边坐标应为r + 1。为什么呢?比如下面这种情况: [1 , 3] , [ 3 , 5],很明显第一个3在位置4才开始起作用,所以计r + 1再排序才能得到正确答案。

c++代码:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e5 + 5;

typedef long long ll;

ll a[maxn] , b[maxn] , c[maxn]; 

struct node {
	ll p , d;
	bool operator < (const node b) const {
		return ( p < b.p ) || ( p == b.p && d > b.d ) ;
	}
	node(ll a , ll b) : p(a) , d(b){}  
};

vector <node> v;

int main() {
	int n;
	ll C;
	cin >> n;
	cin >> C;
	for(int i = 0 ; i < n ; i++) {
		cin >> a[i] >> b[i] >> c[i];
		
		v.push_back( node(b[i] + 1 , - c[i] ));	
		v.push_back( node(a[i] , c[i] ));
		
	}
	sort( v.begin() , v.end() );
	ll ans = 0;
	for(int i = 1 ; i < v.size() ; i++) {
		int t = v[i].p - v[i - 1].p;
		ans += min(C , v[i - 1].d) * t;
		v[i].d += v[i - 1].d;
	}
	cout << ans << "\n";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值