zoukankan      html  css  js  c++  java
  • Codeforces Educational Round 100(Div.2)


     

    A、Dungeon

    题意:

    你现在要打死三个怪物,你的每次攻击可以挑一次怪物降低一点$HP$,且第$7$的倍数次出招可以$AOE$,每个怪物降低一点$HP$,问你能不能最后用$AOE$把它们同时都打死。

    题解:

    每$7$次攻击能造成$9$点伤害,所以总血量是$9$的倍数,且$AOE$次数(总血量除$9$的商)要大于等于最少血的怪物时,就行,否则不行。

    B、Find The Array

    题意:

    给你一个序列$a$,构造一个相同长度的序列$b$,使得$b_i$和$b_{i+1}$其中一个能整除另一个。且$sum limits _{i=1}^{n} |a_i - b_i| imes 2 leq sum limits _{i =1} ^{n} a_i$。

    题解:

    自己想的一个算法:想要每个数都达到$|a_i - b_i | leq a_i$,可以计算出$b_i geq frac{a_i}{2}$且$b_i leq frac{3 imes a_i }{2}$。所以就选择其中一个数固定,然后向左右两边按这个规则扩展,一旦找到答案就输出。

    但是这个太麻烦了。

    注意到题目所求式子,这个暗示了按奇偶分类即可。因为奇数位置和与偶数位置和一定有一个大于等于序列$a$的和的一半,我们只要让$b$中这一半和$a$中一样,其他的是$1$就行了。

    C、Busy Robot

    题意:

    给出$n$个操作,第$i$个操作在$t_i$时刻下达,让机器人从当前位置去$x_i$,如果前面的操作没完成,这个操作忽略,定义一个操作“成功”,是说在$[t_i,t_{i+1}]$时间内的任意时刻,机器人在$x_i$。$t_{n+1} = INF$,按输入顺序操作,问成功的操作次数,保证$t_{i+1}>t_i$。

    题解:

    首先计算出能被执行的操作是什么,然后在这些操作中间,计算出每个时间区间机器人的位置,然后判断操作的目标位置在不在其中,如果在就统计。

    坑点:有的时候机器人跑完了但是计算的时候会被视为仍在跑,计算出的区间不是实际的区间,所以需要$min$和$max$约束一下。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N = 1e5 + 5;
     5 pair<ll, ll> p[N];
     6 int getdir(ll s, ll t)
     7 {
     8     if (s == t)
     9         return 0;
    10     else if (s > t)
    11         return -1;
    12     return 1;
    13 }
    14 bool inrange(ll l, ll r, ll pos)
    15 {
    16     if (l > r)
    17         swap(l, r);
    18     return l <= pos && pos <= r;
    19 }
    20 void solve()
    21 {
    22     int n;
    23     scanf("%d", &n);
    24     for (int i = 1; i <= n; ++i)
    25         scanf("%lld%lld", &p[i].first, &p[i].second);
    26     p[n + 1].first = 1e18;
    27     ll pos = 0, ans = 0;
    28     for (int i = 1; i <= n;)
    29     {
    30         int dir = getdir(pos, p[i].second);
    31         int nxt = i + 1;
    32         while (nxt <= n && p[nxt].first < abs(p[i].second - pos) + p[i].first)
    33             ++nxt;
    34         for (int j = i; j < nxt; ++j)
    35         {
    36             ll l = pos + dir * (p[j].first - p[i].first);
    37             ll r = pos + dir * (p[j + 1].first - p[i].first);
    38             if (dir == -1)
    39                 l = max(l, p[i].second), r = max(r, p[i].second);
    40             else
    41                 l = min(l, p[i].second), r = min(r, p[i].second);
    42             if (inrange(l, r, p[j].second))
    43                 ++ans;
    44         }
    45         pos = p[i].second;
    46         i = nxt;
    47     }
    48     printf("%lld
    ", ans);
    49 }
    50 int main()
    51 {
    52     int t;
    53     scanf("%d", &t);
    54     while (t--)
    55         solve();
    56     return 0;
    57 }
    View Code

    D、Pairs

    题意:

    把$1$到$2 imes n$个数分成$n$个$pair$,对于$x$从$0$到$n$,选出$x$个$pair$取最小值,剩下的取最大值构成给定的序列,问有几个$x$能构造出来。

    题解:

    可以知道这个可行$x$的选取是在一段连续区间上的,因为如果存在多段区间上,它们可以通过交换凑到一个区间上。然后考虑左右端点怎么计算出来,先考虑一定只能选最小值的情况,$n=5$时的$1 2 3 4 5$,如果是$1 2 4 5 6$,则$4 5 6$其中一个可以取最大值,所以我们发现,前面的非连续的区间之间的距离,即上例的$6-4=2$减一,就可以给后面的一个数放到上面,这样子,我们就可以计算出有哪些可以利用这个性质,使得$pair$可以以它为最大值时也合法,反过来也一样。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N = 4e5 + 5;
     5 int a[N];
     6 void solve()
     7 {
     8     int n;
     9     scanf("%d", &n);
    10     for (int i = 1; i <= n; ++i)
    11         scanf("%d", &a[i]);
    12     a[n + 1] = n * 2 + 1;
    13     int ans = n + 1, sum = 0;
    14     for (int i = 1; i <= n; ++i)
    15     {
    16         sum += a[i] - a[i - 1] - 1;
    17         if (sum == 0)
    18             --ans;
    19         else
    20             --sum;
    21     }
    22     sum = 0;
    23     for (int i = n; i; --i)
    24     {
    25         sum += a[i + 1] - a[i] - 1;
    26         if (sum == 0)
    27             --ans;
    28         else
    29             --sum;
    30     }
    31     printf("%d
    ", ans);
    32 }
    33 int main()
    34 {
    35     int t;
    36     scanf("%d", &t);
    37     while (t--)
    38         solve();
    39     return 0;
    40 }
    View Code

    后记:

    不要死板觉得codeforces的D题E题一定是树状数组或者是线段树之类的东西QAQ,还是要多想多思考。

  • 相关阅读:
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1009:带余除法
    1007:计算(a+b)×c的值
    1007:计算(a+b)×c的值
    1007:计算(a+b)×c的值
    1006:A+B问题
    1006:A+B问题
    1006:A+B问题
    C# 运算符 ?、??、?: 、?. 、 各种问号的用法和说明
    C# 运算符 ?、??、?: 、?. 、 各种问号的用法和说明
    在C#中??和?分别是什么意思?
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/14172653.html
Copyright © 2011-2022 走看看