ECNU XCPC 2021 OCTOBER TRAINING #1
诶嘿没想到吧这个博客更新le
A 鸡兔同笼
question
在一个笼子里关着一个头两只脚的鸡,一个头三只脚的东西,一个头四只脚的兔子,给头和脚,求兔子最多最少有几只
sov
直接贪心,兔子最多的时候全是鸡,最少的时候全是猫。解一下方程组即可
ans1 = y - 3 * x;
ans1 = max(0, ans1);
ans2 = y / 2 - x;
cout << ans1 << " " << ans2 << endl;
B 小喵的晚会
question
给一个数列,尽可能的从中减掉最多的值,且操作后的数各不相同
sov
把数组从小到大排序,对每一个数,从小到大枚举它可以剩余的最小的数
sort(a + 1, a + n, cmp);
for(register int i = 1; i < n; ++i)
{
register int j = i;
while(v[j]) ++j;
a[n].num += a[i].num - j;
a[i].num = j;
v[a[i].num] = true;
}
std
从小到大排序,没个数分别拿到只剩1,2,3……
C魔树
question
给一棵树,接下来进行操作
D: 删除所有的叶节点
A k:在每一个叶节点下加k个叶节点
sov
记录每一个点在第几层,然后进行模拟操作
//d是记录每个节点距离最深的子节点多远
inline void dfs(int fa, int x)
{
int mx = 0;
for(register int i = head[x]; i; i = nxt[i])
{
if(ver[i] == fa)
continue;
dfs(x, ver[i]);
mx = max(d[ver[i]], mx);
}
d[x] = mx + 1;
}
int main()
{
//处理每个节点,d是该节点在第几层叶子,cnt是该层有几个叶子
//pt指向当前最深的一层
for(register int i = 1; i <= n; ++i)
{
d[i] = pt - d[i] + 1;
++cnt[d[i]];
}
//A操作只需要下一层有当前层的叶子数 * k
for(register int i = 1; i <= m; ++i)
{
if(c == 'D')
--pt;
else
{
cin >> k;
cnt[pt + 1] = 1ll * cnt[pt] * k % MOD;
++pt;
}
}
}
more
可以使用双端队列维护操作,将重叠的A和D删去,减少操作数(复杂度上没啥变化反正是O(1)操作)