首页 > 其他分享 >AtCoder Regular Contest 116 F Deque Game

AtCoder Regular Contest 116 F Deque Game

时间:2023-04-28 23:24:44浏览次数:40  
标签:AtCoder frac Contest max ll min Deque 序列 return

洛谷传送门

AtCoder 传送门

很强的博弈 + 性质题。下文令 A 为 Takahashi,B 为 Aoki。

发现单独考虑一个序列 \(a_1,a_2,...,a_n\):

  • 若 \(n \bmod 2 = 0\):
    • 若 A 为先手,答案为 \(\max(a_{\frac{n}{2}}, a_{\frac{n}{2} + 1})\);
    • 若 B 为先手,答案为 \(\min(a_{\frac{n}{2}}, a_{\frac{n}{2} + 1})\)(由于 \(\min\) 和 \(\max\) 的对称性)。
    • 双方都是成为先手比成为后手优。
  • 若 \(n \bmod 2 = 1\):
    • 若 A 为先手,答案为 \(\min(a_{\frac{n+1}{2}}, \max(a_{\frac{n+1}{2} - 1}, a_{\frac{n+1}{2} + 1}))\);
    • 若 B 为先手,答案为 \(\max(a_{\frac{n+1}{2}}, \min(a_{\frac{n+1}{2} - 1}, a_{\frac{n+1}{2} + 1}))\);
    • 双方都是成为后手比成为先手优。

相同的结论在 CF794E 也出现过。这是容易归纳证明的,故证明略。

考虑如果全部序列长度都为奇数,容易发现若先手取了其中一个序列的一个数,后手肯定再把这个序列的长度取回奇数。这是因为如果出现了长度为偶数的序列,那它肯定会成为先后手争夺的对象(双方都是成为先手比成为后手优)。所以全部序列的答案可以独立计算再加起来。

现在有一些序列长度为偶数,根据前面的讨论,它们会成为双方争夺的对象。取完偶数的序列后,就回到了上面的情况,并且先后手可能会交换顺序。设 \(x,y\) 为对于一个偶长序列,取头部和取尾部得到的剩下的序列的答案,设 \(mx = \max(x,y), mn = \min(x,y)\),发现肯定是按 \(mx - mn\) 从大到小先手交替地取。因为如果是 A 取了它,它会比 B 取它多了 \(mx - mn\) 的得分,反之如果 B 取了它,它会比 A 取它少 \(mx - mn\) 的得分。

这样最后的答案由两部分组成,一部分是奇长序列的答案,由于可以单独考虑,所以可以提前确定;另一部分是偶长序列的答案,需要先后手交替取完后转化为奇长序列再记入答案。

时间复杂度线性对数,瓶颈在于排序。

code
// Problem: F - Deque Game
// Contest: AtCoder - AtCoder Regular Contest 116
// URL: https://atcoder.jp/contests/arc116/tasks/arc116_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;

ll n;
vector<ll> vc[maxn];

inline bool cmp(pii a, pii b) {
	return a.fst - a.scd > b.fst - b.scd;
}

inline ll calc(vector<ll> &a, int op) {
	ll m = (ll)a.size();
	if (!m) {
		return 0;
	} else if (m == 1) {
		return a[0];
	}
	if (op) {
		if (m & 1) {
			return min(a[m / 2], max(a[m / 2 - 1], a[m / 2 + 1]));
		} else {
			return max(a[m / 2], a[m / 2 - 1]);
		}
	} else {
		if (m & 1) {
			return max(a[m / 2], min(a[m / 2 - 1], a[m / 2 + 1]));
		} else {
			return min(a[m / 2], a[m / 2 - 1]);
		}
	}
}

void solve() {
	scanf("%lld", &n);
	int c = 0;
	for (int i = 1, k, x; i <= n; ++i) {
		scanf("%d", &k);
		while (k--) {
			scanf("%d", &x);
			vc[i].pb(x);
		}
		c += (vc[i].size() % 2 == 0);
	}
	vector<pii> S;
	ll ans = 0;
	if (c & 1) {
		for (int i = 1; i <= n; ++i) {
			if (vc[i].size() & 1) {
				ans += calc(vc[i], 0);
				continue;
			}
			auto a = vc[i], b = vc[i];
			a.erase(a.begin());
			b.pop_back();
			ll x = calc(a, 0), y = calc(b, 0);
			S.pb(max(x, y), min(x, y));
		}
	} else {
		for (int i = 1; i <= n; ++i) {
			if (vc[i].size() & 1) {
				ans += calc(vc[i], 1);
				continue;
			}
			auto a = vc[i], b = vc[i];
			a.erase(a.begin());
			b.pop_back();
			ll x = calc(a, 1), y = calc(b, 1);
			S.pb(max(x, y), min(x, y));
		}
	}
	sort(S.begin(), S.end(), cmp);
	for (int i = 0, o = 1; i < (int)S.size(); ++i, o ^= 1) {
		ans += (o ? S[i].fst : S[i].scd);
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,frac,Contest,max,ll,min,Deque,序列,return
From: https://www.cnblogs.com/zltzlt-blog/p/17363374.html

相关文章

  • AtCoder Regular Contest 123 E Training
    洛谷传送门AtCoder传送门不妨假设\(B_X\leB_Y\)。设\(f(x)=A_X+\frac{x}{B_X},g(x)=A_Y+\frac{x}{B_Y},F(x)=\left\lfloor{f(x)}\right\rfloor,G(x)=\left\lfloor{g(x)}\right\rfloor\),题目即求\(\sum\limits_{x=1}^n[F(x)=G(x)]\)。我一开始尝试化简......
  • vector,list,deque,set,map of STL
    List封装了链表,Vector封装了数组,list和vector得最主要的区别在于vector使用连续内存存储的,他支持[]运算符,而list是以链表形式实现的,不支持[]。Vector对于随机访问的速度很快,但是对于插入尤其是在头部插入元素速度很慢,在尾部插入速度很快。List对于随机访问速度慢得多,因为可能要......
  • AtCoder Regular Contest 126 E Infinite Operations
    洛谷传送门AtCoder传送门算是对这篇博客的补充吧。设\(a_1\lea_2\le\cdots\lea_n\)。发现最优操作中一定是对相邻的数进行操作,因为如果\(a_j\)想把\(x\)给\(a_i\)(\(i<j\)),最优是依次操作\((j-1,j,x),(j-2,j-1,x),...,(i,i+1,x)\)。这样\(x\)就能造成\((j-i)......
  • 【AtCoder】Forbidden Pattern
    题目链接分析首先考虑哪些串能被删空。下面只考虑长度为偶数的串。考虑这样一个(错误的)算法:从左往右依次加入串中的字符,然后能删则删。这个算法对于结尾为A的串一定能删空。对称地,开头为B的串也一定能被删空。现在只需要考虑开头为A结尾为B的串。如果它能被删空,则一定存......
  • AtCoder Regular Contest 112 F Die Siedler
    洛谷传送门AtCoder传送门感觉太人类智慧了。设\(A=(c_1,c_2,...,c_n)\)表示当前每种牌的数量,\(f(A)\)为状态\(A\)只进行换牌操作最终最少剩下几张牌。\(f(A)\)是可以贪心求出的,因为策略必然是能换则换。并且我们发现依次换\(2,3,...,n,1\),最后\(c_2\simc_n\)都......
  • AtCoder Regular Contest 123 C 1, 2, 3 - Decomposition
    洛谷传送门AtCoder传送门从低位往高位考虑。设当前个位为\(k\),暴力搜索这一位向上进\(i\)位,设\(\left\lfloor\frac{n}{10}\right\rfloor-i\)的答案为\(t\)。若\(t>10i+k\)显然就不可行,因为就算个位全部填\(1\)也不能补齐;否则\(n\)的答案就是\(\max(t,\l......
  • AtCoder Regular Contest 120 F Wine Thief
    洛谷传送门AtCoder传送门Hint如果是一个环怎么做?Answer由于是一个环,因此环上每个点对最终答案造成的贡献都相同。设$f_{i,j}$为长度为$i$的序列选$j$个不相邻的点的方案数,则$f_{i,j}=\binom{i-j+1}{j}$。应该很好理解,考虑一个长度为$i-j+1$的链,链头、链尾和两......
  • AtCoder Regular Contest 125 E Snack
    洛谷传送门AtCoder传送门很棒的flow题,考虑建二分图。源点向每种零食连边权为\(a_i\)的边,每种零食向每个孩子连边权为\(b_j\)的边,每个孩子向汇点连边权为\(c_j\)的边,这个图的最大流就是答案。直接跑最大流肯定T,考虑最大流等价于求这个图的最小割,因此转而求最小割。......
  • AtCoder Regular Contest 126 D Pure Straight
    洛谷传送门AtCoder传送门很不错的状压。考虑先把最后作为答案的数聚到一起,再算它们的逆序对个数。设\(f_S\)为当前选的数集合为\(S\)的答案。有转移:选\(a_i\),答案加上之前选的比它大的数;不选\(a_i\),此时需要把左边的数或者右边的数往中间挪一个,答案加上左右两端的最......
  • SMU Spring 2023 Trial Contest Round 10
    SMUSpring2023TrialContestRound10 A-RemoveDuplicates#include<bits/stdc++.h>usingnamespacestd;typedefpair<int,int>PII;typedefpair<string,int>PSI;constintN=2e2+5,INF=0x3f3f3f3f,Mod=1e6;constdoubleeps=1e-6;typedef......