Educational Codeforces Round 85 (Rated for Div. 2)(A~D)

A. Level Statistics

# 题目总链接

思路

  • 题意:给我们n次按时间顺序排序的刷图情况,对于每次刷图情况有两个参数 a、b,a:到目前已经刷了多少次图,b为到目前已经成功刷了所少次图 (注意对于每次刷图a的次数要+1, 可以是成功的刷过去了那么b的数值也要+1,也可以是没有刷过去失败了),让我们判断这个n刷图情况是否符合逻辑
  • 分析:水题一个,但是其中的逻辑还是要搞清楚的
  1. 刷图数量a不能递减,成功刷图数量b也不能递减,
  2. 成功刷图数量b<=刷图数a
  3. 成功刷图数量的增加量 <= 刷图数量的增加量

代码

#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long 
#define INF 0x3f3f3f3f
const int mxn = 3e5;
int ar[mxn], br[mxn];

int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int n;
        scanf("%d", &n);
        int fg = 1;
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d %d", &ar[i], &br[i]);
            if(br[i] > ar[i]) fg = 0;                           //成功刷图的次数 不可能大于 刷图的数量

            if(i >= 2 && fg)
            {
                if(ar[i] < ar[i - 1] || br[i] < br[i - 1])      //刷图的次数和成功完成刷图的次数 都必须是非严格递增的
                    fg = 0;
                else if(br[i] - br[i - 1] > ar[i] - ar[i - 1])  //刷图成功增加的次数 不肯多余 刷图的增加次数
                    fg = 0;
            }
        }
        if(fg)
            printf("YES\n");
        else
            printf("NO\n");

    }


    return 0;
}


B. Middle Class

思路

  • 题意:跟我们n个手中的金钱数量 a 1 , a 2 , , , a n a1,a2,,,a_n ,当一个人手中的钱 a i > = x a_i>=x 的时候被认为是富人,现在政府要增加有钱人的数量,通过选定一些人把它们手中的钱求和,然后在均分给他们,设此时它们手中的钱数为y,如果如果y>=x,那么这些人就都变成富人了,就是通过这个手段 最多可让多少人变成富人?

  • 分析:让序列 a 1 , a 2 , , , a n a1,a2,,,an 按从大到小排序,求一下它们的前缀和sum[i],之后在维护一下 sum[i]/i 的最大值(这个维护的前提是sum[i]/i > x,注意转化为double云算的时候)

代码

#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long 
#define INF 0x3f3f3f3f
const int mxn = 3e5;

ll sum[mxn];

int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        ll n, x;
        scanf("%lld %lld", &n, &x);
        for(int i = 1; i <= n; i ++)
            scanf("%lld", &sum[i]);
        sort(sum + 1, sum + 1 + n, greater<int>());
        int ans = 0;
        for(int i = 1; i <= n; i ++)
        {
            sum[i] += sum[i - 1];
            if(sum[i] >= i * x)
                ans = max(ans, i);
        }
        printf("%d\n", ans);
    }


    return 0;
}


C. Circle of Monsters

思路

  • 题意:n个怪兽顺时针站成一圈,每个怪兽又两个属性,生命值ai,爆炸伤害值bi,我们可以对怪兽进行攻击,每次攻击减少怪兽1生命值,当i怪兽被打死之后,它会爆炸,仅能使i+1位置的怪兽的生命值减少bi(当i==1时,第1只怪兽的生命值减少bn),当一个怪兽的生命值<=0 时被认为是死亡,问我们最少需要多少次攻击把所有的怪兽杀死?

  • 分析:其实我们思考,所有怪兽总的生命值是一定的,要想减少攻击次数,那么就要充分利用它们的爆炸伤害,我们不妨假设它们都爆炸,之后看看剩余的统计一下还有那些怪兽还存活着,在统计一下爆炸后所有活着的怪兽的总的生命值sum,但是我们要想引发这些怪兽一个接一个的爆炸,那么就要先杀死一个怪兽,但是我们不知道杀死那一只最优,所以枚举讨论先杀那一只(我们设先杀死x、位置的那一只),既然先杀死x就不可能就不可能被前一只的怪兽的爆炸所伤,如果x的不能被前一只怪兽给炸死,那么之前我们统计的sum就要减去x被炸之后的生命,减完之后的sum,就是其他怪兽的还活着的总生命,这是可以认为它们已经不回在爆炸了,此时的sum值就是我们还要攻击的次数了

代码

#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long 
#define INF 0x3f3f3f3f
const int mxn = 4e5;

ll sum;
ll a[mxn], b[mxn];
ll c[mxn];

int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++)
        {
            scanf("%lld %lld", &a[i], &b[i]);
            if(i >= 2)
                c[i] = a[i] - b[i - 1];   
        }
        c[1] = a[1] - b[n];
        sum = 0;
        for(int i = 1; i <= n; i ++)
        {
            if(c[i] > 0)
                sum += c[i];
        }
        ll ans = 1e18;
        for(int i = 1; i <= n; i ++)
        {
            if(c[i] > 0)
                ans = min(ans, sum - c[i] + a[i]);
            else
                ans = min(ans, sum + a[i]);
        }
        printf("%lld\n", ans);
    }


    return 0;
}


D. Minimum Euler Cycle

思路

  • 题意:给我们一个有n结点的完全有向图(定义:对于图中任意两个节点:u,v, 总存在两条有向边u–>v、v–>u),问我们将所有的路径都只走一遍,如何走出字典序最小的路径。

  • 分析:画出n == 5 的欧拉环路径
    [ 1 , 2 , 1 , 3 , 1 , 4 , 1 , 5 ] + [ 2 , 3 , 2 , 4 , 2 , 5 ] + [ 3 , 4 , 3 , 5 ] + [ 4 , 5 ] + [ 1 ] [1,2,1,3,1,4,1,5]+[2,3,2,4,2,5]+[3,4,3,5]+[4,5]+[1]

[…] 可以认为是一个区间,对于每个区间中的规律是很好找的,现在我们做的就是输出[l, r] 区间的数字,我们可以用二分找出l所位于的[…]区间,之后在用for循从我们找到的这个区间[…]出开始遍历,当与[l, r]区间重叠的时候,就输出,,,,最后要特判输出最后一个区间的输出

代码

#include<vector>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long 
#define INF 0x3f3f3f3f
const int mxn = 3e5;
ll sum[mxn];
ll n, l,  r;

ll work(ll x)
{
    if(x != n)
    {
        return x * ( 2*n - x - 1);
    }
    else
    {
        x --;
        return x * ( 2*n - x - 1) + 1;
    }
}

int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%lld %lld %lld", &n, &l, &r);
        ll L = 0, R = n;
        ll p;      //找位置
        while(L <= R)
        {
            ll mid = (L + R) >> 1;
            if(work(mid) >= l)
            {
                R = mid - 1;
                p = mid;
            }
            else
            {
                L = mid + 1;
            }

        }

        ll now = work(p - 1);

        for(ll i = p; i < n; i ++)
        {
            for(ll j = i + 1; j <= n; j ++)
            {
                now ++;
                if(now >= l && now <= r)
                    printf("%lld ", i);

                now ++;
                if(now >= l && now <= r)
                    printf("%lld ", j);
                if(now > r)
                    break;
            }
                if(now > r)
                    break;
        }
        if(work(n) == r)
            printf("1");
        printf("\n");
    }


    return 0;
}


原创文章 220 获赞 292 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/105819701