码迷,mamicode.com
首页 > 其他好文 > 详细

s2ojcontest88

时间:2021-07-05 16:41:32      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:scan   push   for   ios   sig   signed   define   while   phi   

走夜路

考虑贪心,显然在价格低的地方要多买电,使电量达到上限或者能到达更便宜的充电站

所以得到一个暴力的想法,对于每一个电站,求出凭借它的电能到达的电站,如果能到更便宜的电站,那么就充能够到达最便宜电站的电,否则在其它比较便宜的电站补电。

然后发现可以考虑反悔,在每一个充电站把电充满,遇到更便宜的充电站时把已经充了的还没有用掉的比当前更贵的电反悔掉。

发现单调队列可以很好的进行这个操作。

步骤:

  1. 把比当前更贵的电弹出。
  2. 用当前的电充满手电筒 (把当前的电和电量放入队尾)
  3. 模拟消耗的电(显然消耗队头比较便宜的电)

Code:

#include <iostream>
#include <cstdio>
#include <queue>
#include <functional>
#include <deque>
#define int long long

using namespace std;

const int N = 1e6 + 10;
int n, t;
int d[N], p[N];
deque<pair<int, int> > q;

signed main()
{
	scanf("%lld%lld", &n, &t);
	int cnt = t;
	int ans = 0;
	for (int i = 1; i <= n; ++i)
	{
		scanf("%lld%lld", &d[i], &p[i]);
		if (d[i] > t)
		{
			puts("-1");
			return 0;
		}
		while (q.size() && q.back().first > p[i])
		{
			ans -= q.back().first * q.back().second;
			cnt += q.back().second;
			q.pop_back();
		}
		q.push_back(make_pair(p[i], cnt));
		ans += p[i] * cnt;
		cnt = d[i];
		while (q.size() && q.front().second <= d[i])
		{
			d[i] -= q.front().second;
			q.pop_front();
		}
		if (q.size() && d[i])
		{
			q.front().second -= d[i];
		}
	}	
	while (q.size())
	{
		ans -= q.front().first * q.front().second;
		q.pop_front();
	}
	cout << ans <<endl;
	return 0;
}

t2

数位 \(dp\) 裸题

奇怪的集训队

二项式反演裸题

\(g(k)\) 表示钦定至少全部都会 \(k\) 种算法的方案数。

\(g(k) = \tbinom{n}{k}(2^{(2^{n-k})}-1)\) 因为在钦定 \(k\) 种算法后,其它算法随意,所以有 \(2^{n-k}\) 种算法组合,每种算法组合都随意存在,所以共有 \(2^{(2^{n-k})}\) 种算法组合的组合,注意算法组合的组合不能为空,所以要 \(-1\)

然后设 \(f(k)\) 表示所有同学全部都会的算法恰好为 \(k\) 种的方案数。

有式子:\(g(k) = \sum_{i=k}^{n}\tbinom{i}{k}f(i)\)

因为对于每种方案,其中都有 \(k\) 种算法可能是被钦定的。

然后只需要二项式反演得到 : \(f(k) = \sum_{i=k}^{n} (-1)^{i-k} \tbinom{i}{k} g(i)\)

要注意 \(2^{(2^{n-k})}\) 中指数要模的是 \(\varphi(p)\)

最短路

显然 \(a\)\(b\) 一定是在最短路上的点,所以先把所有在最短路上的点求出来。

\(1\) 求最短路 \(f_i\), 再从 \(n\) 求最短路\(g_i\),对于每个点 \(i\) 如果 \(f_i + g_i = f_n\) 那么这个点为最短路上的点。

因为先到 \(a\), 再到 \(b\) 所有对于最短路上的点建一个 \(dag\) :对于有边相连的点对,由 \(f_i\) 小的点向 \(f_i\) 大的点连边。

对于每个最短路上的点,如果它是 \(b\) ,那么 \(a\) 就是它的前驱,每个点的前驱就是它直接前驱的前驱并,用 \(bitset\) 维护。

复杂度 \(O((n+m)\lg n + \frac{(n+m)n}{32})\) ,时间给开了 \(2\) 秒,应该不会被卡常

s2ojcontest88

标签:scan   push   for   ios   sig   signed   define   while   phi   

原文地址:https://www.cnblogs.com/youwike/p/14964313.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!