第三天打卡 Educational Codeforces Round 73 (Rated for Div. 2)

时间:2019-12-08
本文章向大家介绍第三天打卡 Educational Codeforces Round 73 (Rated for Div. 2),主要包括第三天打卡 Educational Codeforces Round 73 (Rated for Div. 2)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

A:题意:给一串数列,两个相等能够合并,问是否能凑成2048
从211开始,往下遍历,每一次如果有数字,那么*=2,看最后加和是否大于等于需要的即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int q;
int n;
const int N = 1e3 + 10;
ll s[N];
map<ll, ll>mp;
int main()
{
    q = read();
    while (q--)
    {
        mp.clear();
        n = read();
        upd(i, 1, n)s[i] = read();
        upd(i, 1, n)
        {
            up(j, 0, 40)
            {
                if ((1ll << j)&s[i])
                    mp[j]++;
            }
        }
        ll sum = 0;
        ll need = 1;
        int flag = 1;
        dwd(i, 11, 0)
        {
            if (mp[i]+sum >= need)
            {
                flag = 0;
                break;
            }
            else
            {
                sum *= 2;
                sum += mp[i] * 2;
                need *= 2;
            }
        }
        if (!flag)
        {
            printf("yes\n");
        }
        else printf("no\n");
    }
}

B:题意:给一个棋盘,放象棋 的马,问最大互相攻击。
dfs即可。


C:二分一下即可。cf老套路了。


D:dp
题意:给一串序列a,要使得a序列相邻两项不相等。使ai上升1需要花费bi,问最小花费。
我么能够发现,除了第一个和最后一个,中间每一个被夹在了两个之间,那么,意味着中间每一个不能取的数字至多两个,所以我们假设x不能取,那么我们加1,变成x+1,如果x+1还是不能取,变成x+2,x+2一定是不和相邻元素相同的数字。
所以我们就有了dp策略,每一个数字至多上升2,便能完全使得数组没有相邻相同元素。
令dp[i][j]表示第i个上升j的时候哦,前面所有数字满足题意的最小花费。
就有转移
(ai-1+k!=ai+j) dp[i][j]=dp[i-1][k]+j*bi

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int q;
int n;
const int N = 3e5 + 10;
ll a[N], b[N];
ll dp[N][5];
int main()
{
    q = read();
    while (q--)
    {
        n = read();
        upd(i, 1, n)
            a[i] = read(), b[i] = read();
        upd(i, 1, n)
            upd(j, 0, 2)dp[i][j] = 1e18 + 1;
        upd(i, 1, n)
        {
            upd(j, 0, 2)
            {
                upd(k, 0, 2)
                {
                    if (a[i - 1] + j == a[i] + k)continue;
                    dp[i][k] = min(dp[i][k], dp[i - 1][j] + 1ll*k * b[i]);
                }
            }
        }
        ll minans = 1e18 + 1;
        upd(j, 0, 2)
            minans = min(dp[n][j], minans);
        printf("%lld\n", minans);
    }
    return 0;
}

E题:题意:
给01字符串,0的位置能被替换成为1,现在x和y博弈,x先手,每一次x能反转a个0到1,y能反转b个零到1,当到某个人的回合时,如果某个人没有再能反转的输。
首先有个重要的条件,a>b,这就意味着,有小区间,b能覆盖而a不能。我们以此入手。
1.当存在区间,a>区间长度>=b,这就意味着只能b取覆盖而a不能。如果x想赢得比赛,那么x一定在最后会取覆盖长度为a的区间,那么这个时候y如果再上一步,就将这个区间覆盖掉,那么x必输,因为只剩下a>len>=b的区间。
2.如果>=2b的区间多于两个,那么就可以转换成为上述情况,因为x先手可能破坏掉一个,那么y后手至少有一个2b的区间,这个时候只要选择覆盖掉后这个区间剩余长度在a~b之间即可,也就是第一种情况,那么x必输。
3.如果2b区间为零。那么意味着所有区间长度都在2b>len>=a,那么只需要判断所有区间的数量即可,因为相当于x和y每一次覆盖掉一个区间后,这个区间就再也不能覆盖新的了。
4.如果2b有一个区间。那么我们遍历这个区间长度,每一次取a,判断左右两边的情况,看x是否能赢。左右两边首先不能出现上面1,2的情况不然必输。所以只能是第三种情况,在判断奇偶即可。
那么我们最后看一看如果2
b<a了,看第一种情况,没有变化,第二种情况,还是没有变化。第三种情况,如果2b的区间为零,a区间那么就为零,x必输。
第四种情况,如果有2
b区间,这个区间就是a>len>2*b>=b,回到第一种情况。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 3e5 + 10;
int q;
int a, b;
string s;
int cnt[N];
int main()
{
    q = read();
    while (q--)
    {
        a = read(), b = read();
        cin >> s;
        int n = s.size();
        int top = 0;
        bool flag = 0;
        memset(cnt, 0, sizeof(cnt));
        up(i, 0, n)
        {
            if (s[i] == '.')
            {
                if (!flag)++top, flag = 1;
                cnt[top]++;
            }
            else flag = 0;
        }
        int cnta = 0; int cntb = 0; int cntc = 0;
        int pos;
        upd(i, 1, top)
        {
            if (cnt[i] >= b && cnt[i] < a)cntc = 1;
            if (cnt[i] >= 2 * b)cntb++,pos=i;
            if (cnt[i] >= a)cnta++;
        }
        if (cntc)
        {
            printf("no\n");
            continue;
        }
        if (cntb >= 2)
        {
            printf("no\n");
            continue;
        }
        if (cntb == 0)
        {
            if (cnta & 1)printf("yes\n");
            else printf("no\n");
            continue;
        }
        bool ok = 0;
        upd(i, 0,  cnt[pos]-a)
        {
            int left = i;
            int right = cnt[pos] - i - a;
            if (left >= b && left < a || right >= b && right < a)continue;
            if (left >= 2 * b || right >= 2 * b)continue;
            int temp = (cnta + (left >= a) + (right >= a));
            if (temp % 2)
                ok = 1;
        }
        if (ok)printf("yes\n");
        else printf("no\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/LORDXX/p/12004782.html