C
题意:一棵树,边有边权,边权可修改。每次选一条路径,将该路径所有边边权-1,对当前树求将所有边清空的最小操作次数。
思路:对每个点,维护以当前点为lca路径条数。考虑该点向下的边的最大值,如果最大值减去向上的边的差大于其他向下的边的和,那么就可以两两匹配,否则最大边会有剩余。
D
题意:看题面吧qwq
双方各有五类兵。
1类:有盾+能召唤5,体力1e9
2类:有盾,体力1e9
3类:能召唤5,体力1e9
4类:体力1e9
5类:体力1
每一次,有A确定挑战方案,问A是否能赢。
思路:贪心。
5类兵除了消耗盾牌,没有什么用。
A方用兵顺序为3124,B方为3412
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a[10], b[10];
int main()
{
int T;
scanf("%d", &T);
while(T)
{
T--;
for(int i = 1; i <= 4; i++)
scanf("%d", &a[i]);
for(int i = 1; i <= 4; i++)
scanf("%d", &b[i]);
a[5] = b[5] = 0;
while(a[1] + a[2] + a[3] + a[4] && b[1] + b[2] + b[3] + b[4])
{
if(a[3] + a[4]) b[5] = 0;
if(a[5])
{
if(b[1])
{
b[1]--;
b[3]++;
a[5]--;
}
else
if(b[2])
{
b[2]--;
b[4]++;
a[5]--;
}
}
if(a[3])
{
a[3]--;
a[5]++;
}
else
{
if(a[1])
{
a[1]--;
a[3]++;
}
else
{
if(a[2])
{
a[2]--;
a[4]++;
}
else
{
a[4]--;
}
}
}
if(b[3])
{
b[3]--;
b[5]++;
}
else
{
if(b[4])
{
b[4]--;
}
else
{
if(b[1])
{
b[1]--;
b[3]++;
}
else
{
b[2]--;
b[4]++;
}
}
}
}
if(a[1] + a[2] + a[3] + a[4] || ((b[1] + b[2] + b[3] + b[4] == 0) && a[5] > b[5]))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
E
题意:积木,可以向左推某一行,如果下面空了就会向下掉,求最低高度。
思路:二分答案,如果当前列高于答案,看左侧有没有剩余。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
const int N = 2e5 + 10;
LL a[N];
int judge(int n, LL x)
{
LL sum = 0;
for(int i = 1; i <= n; i++)
{
if(a[i] < x)
sum+= x - a[i];
if(a[i] > x )
sum -= a[i] - x;
if(sum < 0)
return 0;
}
if(sum >= 0)
return 1;
return 0;
}
int main()
{
int T,n;
scanf("%d", &T);
while(T)
{
T--;
scanf("%d", &n);
LL maxa = 0;
for(int i = 1; i <= n; i++)
{
cin>>a[i];
maxa = max(maxa, a[i]);
}
LL R = maxa;
LL L = 0;
while(R - L > 1)
{
LL mid = (L + R) >> 1;
if(judge(n, mid))
R = mid;
else
L = mid;
}
cout<<R<<endl;
}
return 0;
}