1. 水杯
签到题
code
#include <cstdio>
using namespace std;
typedef long long ll;
int main()
{
#ifdef LZH_LOCAL
freopen("in.in", "r", stdin);
// freopen("out.out", "w", stdout);
#endif
int n, L, A, B;
scanf("%d%d%d%d", &n, &L, &A, &B);
int v = 0, w = -1000;
while (n--)
{
int a, x;
scanf("%d", &a);
if (a == 1)
{
scanf("%d", &x);
w = x;
}
else if (a == 2)
{
scanf("%d", &x);
v = x;
}
else
{
if (v >= L && w >= A && w <= B)
printf("%d\n", w);
else
puts("GG");
}
}
return 0;
}
2. 鳖
模拟题。a[i]、b[j] 两个数组记下Alice和Bob的所有牌,aa[i]、bb[j] 数组标记牌在不在手上,ma[x]、mb[y] 标记牌面=x或y 的牌的上一张的位置,也可以用map标记,然后模拟摸牌即可。
code
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int a[N * 2], b[N * 2];
bool aa[N * 2], bb[N * 2];
bool ma[N * 2], mb[N * 2]; //ma[x] = 1/0 表示 A 手上有没有 x 这个牌
int main()
{
#ifdef LZH_LOCAL
freopen("in.in", "r", stdin);
// freopen("out.out", "w", stdout);
#endif
int n;
scanf("%d", &n);
int ta = 1, tb = 1;
int suma = 0, sumb = 0;
for (int i = 1; i <= 4 * n - 2; i++)
{
int x;
scanf("%d", &x);
if (i & 1)
{
a[ta] = x;
if (ma[x])
{
aa[ma[x]] = 1;
aa[ta] = 1;
ma[x] = 0;
suma--;
}
else
{
ma[x] = ta;
suma++;
}
ta++;
}
else
{
b[tb] = x;
if (mb[x])
{
bb[mb[x]] = 1;
bb[tb] = 1;
mb[x] = 0;
sumb--;
}
else
{
mb[x] = tb;
sumb++;
}
tb++;
}
}
int i = 0, j = 0;
int cnt = 0;
while (suma && sumb)
{
cnt++;
if (cnt & 1)
{
// Alice摸对方的第一张牌
for (j = j + 1; j < tb; j++)
if (!bb[j])
break;
a[ta] = b[j];
sumb--;
mb[b[j]] = 0;
bb[j] = 1;
if (ma[a[ta]])
{
aa[ma[a[ta]]] = 1;
aa[ta] = 1;
ma[a[ta]] = 0;
suma--;
}
else
{
ma[a[ta]] = ta;
suma++;
}
ta++;
}
else
{
// Bob摸对方的第一张牌
for (i = i + 1; i < ta; i++)
if (!aa[i])
break;
b[tb] = a[i];
suma--;
ma[a[i]] = 0;
aa[i] = 1;
if (mb[b[tb]])
{
bb[mb[b[tb]]] = 1;
bb[tb] = 1;
mb[b[tb]] = 0;
sumb--;
}
else
{
mb[b[tb]] = tb;
sumb++;
}
tb++;
}
}
printf("%d\n", cnt);
return 0;
}
3. 顺序安排
这题自己直觉可能有两种情况排列
然后考虑怎么把答案计算出来,求出每棵子树的结点个数,然后枚举所有结点,把该节点所有的儿子节点的子树大小排序,计算所有儿子到父亲节点对答案的贡献。
此题解释可参考这篇博客
code
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
template <typename T>
void read(T &t)
{
t = 0;
T f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
f *= -1;
ch = getchar();
}
while (isdigit(ch))
{
t = t * 10 + ch - 48;
ch = getchar();
}
t *= f;
}
int cnt[maxn];
vector<int> v[maxn], p;
// 求子树结点的个数
void dfs(int u)
{
cnt[u] = 1;
int t = v[u].size();
for (int i = 0; i < t; i++)
{
int e = v[u][i];
dfs(e);
cnt[u] += cnt[e];
}
}
bool cmp(int a, int b) { return cnt[a] < cnt[b]; }
int main()
{
#ifdef LZH_LOCAL
freopen("in.in", "r", stdin);
// freopen("out.out", "w", stdout);
#endif
int n, m;
read(n), read(m);
for (int i = 2; i <= n; i++)
{
int x;
read(x);
v[x].push_back(i);
}
dfs(1); //求出每棵子树结点的个数 cnt[]
ll ans = 1; //根节点1的贡献点是1
// 分别对 每个结点作为根节点时 计算它的子节点的贡献值
for (int i = 1; i <= n; i++)
{
p.clear();
int t = v[i].size();
for (int j = 0; j < t; j++)
p.push_back(v[i][j]);
// 把结点i的所有儿子结点按照子树结点个数从小到大排序
sort(p.begin(), p.end(), cmp);
ll temp = 1;
// 计算结点i的子节点到i的贡献点
t = p.size();
for (int j = 0; j < t; j++)
{
int x = p[j];
ans += temp;
temp += cnt[x];
}
}
printf("%lld\n", ans * m);
return 0;
}