题解2020联合省选A卷-Day1

Posted top_secret的小尛博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解2020联合省选A卷-Day1相关的知识,希望对你有一定的参考价值。

冰火战士

有关卡常

看到\\(2\\times 10^6\\):卡常???那我写树状数组!!

树状数组怎么二分?见这篇CF上的文章

有关如何二分

\\(a_i\\)表示温度为\\(i\\)的冰战士的

因为实际上求的是

\\[\\max_i\\left\\{\\min\\left\\{\\sum_{j\\le i}a_j,\\sum_{j\\ge i}b_j\\right\\}\\right\\} \\]

而这个形式很难快速求。但是考虑到所有\\(a_i,b_i\\ge 0\\),考虑取最大值时\\(\\min\\)内哪个较小,有两种请况:

  1. 此时\\(\\sum_{j\\ge i}b_j<\\sum_{j\\le i}a_j\\),且\\(\\sum_{j\\ge i}b_j\\)最大,\\(i\\)最大。
  2. 此时\\(\\sum_{j\\ge i}b_j\\ge \\sum_{j\\le i}a_j\\),且\\(\\sum_{j\\le i}a_j\\)最大,\\(i\\)最大。

由于1、2类似,下面只考虑第一种情况:

\\(sumB=\\sum_ib_i\\),则可如下变形:

\\[\\begin{aligned} \\sum_{j\\ge i}b_j&<\\sum_{j\\le i}a_j \\\\ sumB-\\sum_{j<i}b_j&<\\sum_{j\\le a_j} \\\\ sumB &< \\sum_{j\\le i} a_j+b_{j+1} \\end{aligned} \\]

故在\\(\\{a_i+b_{i+1}\\}\\)上二分即可以求得最小的\\(i\\),使得以上等式成立。

此时,需要在使得\\(\\sum_{j\\le i}b_j\\)不变的前提下,\\(i\\)尽量大,再在\\(\\{b_i\\}\\)上二分一次即可。

AC(考场)代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)

const int Q = 2e6+10, P = 1<<20;

int q;
int op[Q], t[Q], x[Q], y[Q], k[Q];
int a[Q];

struct BIT{
	int t[Q];
	void add(int x, int d) {
		for (; x < Q; x += x&-x) t[x] += d;
	}
	int sum(int x) {
		int ret = 0;
		for (; x; x -= x&-x) ret += t[x];
		return ret;
	}
	int min_g(int x) {
		int sum = 0, cur = 0;
		for (int k = P; k; k >>= 1) if (cur+k < Q && sum+t[cur+k] <= x) {
			sum += t[cur+=k];
		}
		return cur+1;
	}
	int max_le(int x) {
		return min_g(x)-1;
	}
}A, B, AB;

int sumA, sumB;

#define debug printf

signed main() {
	freopen("icefire.in", "r", stdin);
	freopen("icefire.out", "w", stdout);
	scanf("%lld", &q);
	int m = 0;
	for (int i = 1; i <= q; ++i) {
		scanf("%lld", &op[i]);
		if (op[i] == 1) {
			scanf("%lld%lld%lld", t+i, x+i, y+i);
			a[++m] = x[i];
		} else {
			scanf("%lld", k+i);
		}
	}
	sort(a+1, a+m+1);
	m = unique(a+1, a+m+1)-(a+1);
	B.add(m+2, 1);
	AB.add(m+2, 1);
	for (int i = 1; i <= q; ++i) {
		if (op[i] == 1) {
			x[i] = lower_bound(a+1, a+m+1, x[i])-a;
		}
	}
	//debug("unique: %lld\\n", m);
	for (int i = 1; i <= q; ++i) {
		if (op[i] == 1) {
			if (t[i] == 0) A.add(x[i], y[i]), sumA+=y[i];
			if (t[i] == 1) B.add(x[i]+1, y[i]), sumB+=y[i];
			AB.add(x[i]+(t[i]==1), y[i]);
		} else {
			if (t[k[i]] == 0) A.add(x[k[i]], -y[k[i]]), sumA-=y[k[i]];
			if (t[k[i]] == 1) B.add(x[k[i]]+1, -y[k[i]]), sumB-=y[k[i]];
			AB.add(x[k[i]]+(t[k[i]]==1), -y[k[i]]);
		}
		int ans = 0, power = 0;
		int ret1 = AB.min_g(sumB), ret2 = ret1-1; ret1 = B.max_le(B.sum(ret1));
		int ans1 = min(A.sum(ret1), sumB-B.sum(ret1));
		if (ans1 > power || (ans1 == power && ret1 > ans)) power = ans1, ans = ret1;
		int ans2 = min(A.sum(ret2), sumB-B.sum(ret2));
		if (ans2 > power || (ans2 == power && ret2 > ans)) power = ans2, ans = ret2;
		if (!power) puts("Peace");
		else printf("%lld %lld\\n", a[ans], power*2);
	}
}

组合数问题

定义

下降阶乘幂

\\[n^{\\underline{k}} = n(n-1)(n-2)\\cdots(n-k+1) \\qquad n\\in R,k \\in N\\\\ \\]

特别地,\\(n^{\\underline{0}}=1\\);对\\(n\\in N, k>n\\)\\(n^{\\underline{k}}=0\\)

(广义)二项式系数

\\[{n\\choose k} = \\frac{n^{\\underline k}}{k^{\\underline k}} \\qquad n\\in R, k\\in N \\]

特别地,对\\(n\\in N, k>n\\)\\({n\\choose k}=0\\)

结论

前置性质:对\\(i\\le k, i\\in N\\),有\\(n^{\\underline{k}}=n^{\\underline{i}}(n-i)^{\\underline{k-i}}\\)

\\[{n\\choose k}=\\frac{n^{\\underline{k}}}{k^\\underline{k}} = \\frac{n^\\underline i(n-i)^\\underline{k-i}}{k^\\underline i (k-i)^\\underline{k-i}} = \\frac{n^\\underline i}{k^\\underline i}\\cdot{n-i \\choose k-i} \\]

预处理

\\(f(x)=\\sum_ia_ix^i\\)化为下降阶乘幂的形式\\(=\\sum_ib_ix^{\\underline i}\\)

方法:DP(朴素多项式乘法)预处理出对所有\\(i\\)\\(x^{\\underline i}=\\sum_{j=0}^if_{i,j}x^{j}\\)的系数\\(f_{i,j}\\)。之后用多项式减法。

推式子

\\[\\begin{aligned} &\\sum_{k=0}^n f(k)x^k{n\\choose k} \\\\ =&\\sum_{k=0}^n \\sum_{i=0}^m b_i k^{\\underline i} x^k\\cdot\\frac{n^{\\underline i}}{k^\\underline i}{n-i\\choose k-i} \\\\ =&\\sum_{i=0}^m b_i n^{\\underline i}x^i \\sum_{k=0}^n {n-i\\choose k-i}x^{k-i} \\\\ =&\\sum_{i=0}^m b_in^{\\underline i}x^i (1+x)^{n-i} \\end{aligned} \\]

由于\\(m\\le 1000\\),可以随便做。

以上是关于题解2020联合省选A卷-Day1的主要内容,如果未能解决你的问题,请参考以下文章

[省选联考 2020 A 卷] 组合数问题 题解

luoguP6623 [省选联考 2020 A 卷] 树(trie树)

luoguP6620 [省选联考 2020 A 卷] 组合数问题(斯特林数)

省选水题集Day1一起来AK水题吧! 题解(更新到A)

P6627 [省选联考 2020 B 卷] 幸运数字

联合省选 2023 游记