模拟题

首先,题面简短,是道思维好题。我们仔细想想,可以先推出几个简单但正确的性质。

  1. 如果当前最强蛇吃了最弱蛇后,不是最弱,那么一定可以吃。(简要证明:因为吃后不是最弱,所以如果原先次强蛇选择吃,那么他会成为比原先最强蛇消弱后更弱的蛇。因为每一条蛇都会选择最优策略,都不想被吃,那么如果原先次强蛇选择吃,就能保证他不会死,那么比他强的原先最强蛇也不会死;如果原先次强蛇不吃,那么游戏结束,依旧不会死)。

  2. 在保证1成立的基础上,生成的新蛇越来越弱(易证)。

那么唯一的问题就是如果最强蛇吃了后,变成了最弱,那么这个决策是否有执行的必要?

这是本道题的第二阶段。

我们可以递归地思考问题,如果下一条决策蛇吃了原蛇后不是最弱,他肯定会吃。如果下一条决策蛇吃了原蛇后,只剩他自己,他也肯定会吃。其余情况递归解决。至于程序实现,就是迭代。我们也只要注意递归次数奇偶性,因为决策优劣性是交替的。

那么问题迎刃而解,你认为你AC了,可是你发现你TLE了!

原来这题卡 O(nlog2n) 的做法,不能用set乱搞。

我们想起来有一年NOIp考了一题叫蚯蚓,也是卡O(nlog2n) 的做法。那道题,我们发现了单调性,用队列做好的。

你难道以为题目中输入数据的单调性是没用的吗?

根据性质2,在第一阶段,生成蛇有单调性,所以直接两个队列维护。一个维护原蛇,另一个维护变蛇,都是单调的。

第二阶段同理,只要注意最后判断的细节就好啦!

code:

// Program written by Liu Zhaozhou ~~~
#include <bits/stdc++.h>

using namespace std;

inline char gc(void) {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

template <class T> inline void read(T &x) {
	T f = 1; x = 0; static char c = gc();
	for (; !isdigit(c); c = gc()) if (c == '-') f = -f;
	for (; isdigit(c); c = gc()) x = (x << 1) + (x << 3) + (c & 15);
	x *= f;
}

inline void readstr(char *s) {
	do *s = gc(); while ((*s == ' ') || (*s == '\n') || (*s == '\r'));
	do *(++s) = gc(); while ((~*s) && (*s != ' ') && (*s != '\n') && (*s != '\r'));
	*s = 0; return;
}

inline void readch(char&x) { while (isspace(x = gc())); }

char pf[100000], *o1 = pf, *o2 = pf + 100000;
#define ot(x) (o1 == o2 ? fwrite(pf, 1, 100000, stdout), *(o1 = pf) ++= x : *o1 ++= x)
template <class T>
inline void println(T x, char c = '\n') {
	if (x < 0) ot(45), x = -x;
	static char s[15], *b; b = s;
	if (!x) *b ++= 48;
	for (; x; * b ++= x % 10 + 48, x /= 10);
	for (; b-- != s; ot(*b)); ot(c);
}

template <class T> inline void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + 48);
}

template <class T> inline void writeln(T x, char c = '\n') { write(x); putchar(c); }
template <class T> inline void chkmax(T &x, const T y) { x > y ? x = x : x = y; }
template <class T> inline void chkmin(T &x, const T y) { x < y ? x = x : x = y; }

#define Ms(arr, opt) memset(arr, opt, sizeof(arr))
#define Mp(x, y) make_pair(x, y)

typedef long long ll;
typedef pair <int, int> pii;

const int Maxn = 1e6 + 5;
int T, n, a[Maxn];

inline int solve(void) {
	deque <pii> q1, q2; int ret = 0;
	for (int i = 1; i <= n; i++) q1.push_back(Mp(a[i], i));
	while (true) {
		if (q1.size() + q2.size() == 2) return 1;
		int x, y, idx; y = q1.front().first; q1.pop_front();
		if (q2.empty() || (!q1.empty() && q1.back() > q2.back())) {
			x = q1.back().first; idx = q1.back().second; q1.pop_back();
		} else {
			x = q2.back().first; idx = q2.back().second; q2.pop_back();
		} pii cur = Mp(x - y, idx);
		
		if (q1.empty() || q1.front() > cur) {
			ret = (int) q1.size() + (int) q2.size() + 2; int cnt = 0;
			while (true) {
				++cnt;
				if ((int) q1.size() + (int) q2.size() == 1) {
					if (cnt % 2 == 0) --ret; break;
				}
				
				int x, idx;
				if (q2.empty() || (!q1.empty() && q1.back() > q2.back())) {
					x = q1.back().first; idx = q1.back().second; q1.pop_back();
				} else {
					x = q2.back().first; idx = q2.back().second; q2.pop_back();
				}
				
				cur = Mp(x - cur.first, idx);
				if (!((q1.empty() || cur < q1.front()) && (q2.empty() || cur < q2.front()))) {
					if (cnt % 2 == 0) --ret; break;
				}
			} break;
		} else q2.push_front(cur);
	} return ret;
}

signed main(void) {
	read(T);
	for (int i = 1; i <= T; i++) {
		if (i == 1) {
			read(n);
			for (int j = 1; j <= n; j++) read(a[j]);
		} else {
			int k; read(k);
			for (int j = 1, x, y; j <= k; j++)
				read(x), read(y), a[x] = y;
		} writeln(solve());
	}
//	fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

/**/


posted @   EternalEpic  阅读(36)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示