牛客多校训练营2020第10场

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
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#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; 
} 

你可能感兴趣的:(训练赛)