Codeforces Round #693 (Div. 3)
比赛链接
Codeforces Round #693 (Div. 3)
D.Even-Odd Game
Alice 和 Bob 玩游戏
给定含 \(n\) 个数字的数列 \(\{a\}\)
两人轮流进行游戏,Alice 先手
每一轮一人从数列中选取一个数字并将这个数字从数列中删掉
如果 Alice 选择的数字是偶数,那么 Alice 得分加上这个数字,否则 Alice 不加分
如果 Bob 选择的数字是奇数,那么 Bob 得分加上这个数字,否则 Bob 不加分
假设二人都采取最优策略,最后得分高的获胜,请输出胜者(Alice 或者 Bob),或者指明这是平局(Tie)
输入
多组测试数据
先输入 \(T\) 表示有 \(T\) 组测试数据(\(1\le T \le 10^4\))
接下来 \(T\) 组数据,每组数据先输入 \(n\)(\(1\le n \le2\cdot10^5\)),接下来 \(n\) 个数字描述数列 \(\{a\}\)
保证每个测试点 \(T\) 组数据的 \(n\) 之和不超过 \(2\cdot10 ^5\)
输出
每组数据一行
- 如果 Alice 赢了,输出
Alice
- 如果 Bob 赢了,输出
Bob
- 如果二人得分相同,输出
Tie
解题思路
博弈论
博弈策略:两人都选择最大的数
假设两人某时刻分数为 \(x,y\),最终结果为两者的差值 \(x-y\),现在轮到先手决策,假设现在最大值为 \(z\),如果先手选择该数,若该数为偶数,则最终差值为 \(x+z-y\),此时选最大值对先手最优,反之如果该数为奇数,\(z\) 本来是作为 \(y\) 的一部分,但被先手选择了,即最终差值为 \(x-(y-z)=x+z-y\),相当于给先手加分了,故每次选择最大值为最优策略
- 时间复杂度:\(O(nlogn)\)
代码
// Problem: D. Even-Odd Game
// Contest: Codeforces - Codeforces Round #693 (Div. 3)
// URL: https://codeforces.com/contest/1472/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=2e5+5;
int t,n,a[N];
int main()
{
for(cin>>t;t;t--)
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n,greater<int>());
LL res=0;
for(int i=1;i<=n;i++)
{
if(i&1)
{
if(a[i]%2==0)res+=a[i];
}
else if(a[i]&1)
res-=a[i];
}
if(res==0)puts("Tie");
else if(res>0)puts("Alice");
else
puts("Bob");
}
return 0;
}
E. Correct Placement
Polycarp想要给他的朋友们拍一张照片,他的朋友们都有h(身高)、w(宽度)两个数值,当一个人A的身高比另外一个人B的身高矮,且宽度比他小时,A可以站在B的前面,或者当A身高比B宽度小时,且宽度比B身高小时,A可以躺在B前面(小,意为严格小于)。
现在Polycarp想知道每个人是否有对应的人可以站或躺在他的前面,如果有,则输出那个人的编号,若有多个,则输出任意一个,如果没有则输出-1。
输入:第一行一个整数t,代表t组数据。
接下来一个整数n,代表n个人。
随后n行,每行两个整数,代表每个人的宽度和身高。
输出:一共有t组,每组n个整数,代表可以站在第i个人前面的人的编号。
解题思路
思维
要求为每个二元组 \((W,H)\) 找到另外一个 \((w,h)\) 或 \((h,w)\) 使得 \(W>w \&\& H>h\) 或 \(W>h \&\& H>w\),即 \((W,H)\) 的最大值和最小值分别大于 \((w,h)\) 的最大值和最小值,可先按第一关键字排序,在按第二关键字排序,由于是按第一关键字排序,所以对于每个数答案一定在前面,所以可以遍历对每个数求解答案,即记录每个数前面第一关键字不同且第二关键字最小的下标,然后判断该下标是否满足要求,\(\color{red}{那什么时候更新下标?}\) 设置一个变量 \(s\),表示第一关键字相同时最小的第二关键字的下标,当出现不同第一关键字时,由于 \(s\) 表示的是不同的第一关键字,此时考虑是否更新下标,同时更新变量 \(s\)
- 时间复杂度:\(O(nlogn)\)
代码
// Problem: E. Correct Placement
// Contest: Codeforces - Codeforces Round #693 (Div. 3)
// URL: https://codeforces.com/contest/1472/problem/E
// Memory Limit: 256 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=2e5+5,inf=0x3f3f3f3f;
int t,n,res[N];
struct A
{
int x,y,id;
bool operator<(A &o)
{
return (x<o.x||(x==o.x&&y<o.y));
}
}a[N];
int main()
{
for(cin>>t;t;t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].x>>a[i].y;
if(a[i].x>a[i].y)swap(a[i].x,a[i].y);
a[i].id=i;
res[i]=-1;
}
sort(a+1,a+1+n);
int id=0,k=0,s=0;
a[0]={inf,inf,-1};
for(int i=1;i<=n;i++)
{
if(a[i].x!=a[i-1].x)
{
if(a[id].y>a[s].y)id=s;
s=i;
}
if(a[i].y>a[id].y)res[a[i].id]=a[id].id;
}
for(int i=1;i<=n;i++)cout<<res[i]<<' ';
puts("");
}
return 0;
}