ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF #800 div 2

2022-06-21 19:02:17  阅读:168  来源: 互联网

标签:10 typedef 800 int CF long maxn div include


别问我为什么写简体了,问的话就换成繁体

A. Creep

贪心,\(01\) 交替放。

点击查看代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <list>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int maxn = 8e4 + 10, maxe = 8e4 + 10, maxt = maxn * 600;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

char getFunc()
{
    char c;
    while (!isalpha(c = getchar()))
    {
    }
    return c;
}

int main()
{
    int T = read();
    while (T--)
    {
        int a = read(), b = read();
        if (a >= b)
        {
            while (b)
            {
                --a;
                --b;
                putchar('0');
                putchar('1');
            }
            while (a)
            {
                --a;
                putchar('0');
            }
        }
        else
        {
            while (a)
            {
                --a;
                --b;
                putchar('1');
                putchar('0');
            }
            while (b)
            {
                --b;
                putchar('1');
            }
        }
        putchar('\n');
    }
}

B. Paranoid String

可以发现:

\(0000000001\)

\(1111111110\)

都很容易消掉。

然后如果一个串的末尾是 \(01\)

比如 \(100100001\)

发现都可以消成 \(000000001\) 的形式。

如果末尾是 \(10\)

都可以消成 \(11111110\) 的形式。

末尾是 \(00\) \(11\) 就不行了。

这样我们就知道只要一个串的末尾是 \(01\) 或 \(10\) 就能消掉。

串长为 \(1\) 单独另处理就行。

点击查看代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <list>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int maxn = 2e5 + 10, maxe = 8e4 + 10, maxt = maxn * 600;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

char getFunc()
{
    char c;
    while (!isalpha(c = getchar()))
    {
    }
    return c;
}

char str[maxn];

int main()
{
    int T = read();
    while (T--)
    {
        int n = read();
        scanf("%s", str);
        ll ans = n;
        for (int i = 1; i < n; ++i)
        {
            if (((str[i - 1] - '0') ^ (str[i] - '0')) == 1)
            {
                ans += i;
            }
        }
        printf("%lld\n", ans);
    }
}

C. Directional Increase

简单分析可以看出:

每次要让一个位置加一,就需要从它往右移,而且他右边的某个位置还得减一。

如果要让一个位置减一,就需要从它往左移,并且它左边的一个位置还得加一。

这样我们得出如果所有数的和不为零则显然无解。

要在第一个位置加数字,要保证进和出第一个位置的次数都等于需要在这个位置上加的数字。并且因为第一个位置不能左移,所以第一个位置上的数不能减,所以必须要保证第一个位置上的数大于零。

我们可以发现如果把第一个位置上需要累加的数都放到第二个位置上面,这时候第二个位置及其后面的数构成的新问题与原问题是等价的。

比如我第一个数要加 2,那么我可以右移再左移再右移再左移,这样第一个数加了 2,第二个数减了 2,就需要多加一个 2,处理第二个数的过程可以插在几次左右移中间。

因此可以求下前缀和,每次前缀和 > 0 说明可以转化成新问题,< 0 说明无解,如果前缀和 = 0 就说明此时必须待在原位置保持不动,若前缀和后面还有不为 0 的数就判无解。

点击查看代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <list>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int maxn = 2e5 + 10, maxe = 8e4 + 10, maxt = maxn * 600;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

char getFunc()
{
    char c;
    while (!isalpha(c = getchar()))
    {
    }
    return c;
}

int num[maxn];
int n;

bool Check()
{
    ll sum = 0;
    for (int i = 1; i <= n; ++i)
    {
        sum += num[i];
        if (sum < 1 && i != n)
        {
            return 0;
        }
    }
    if (!sum)
    {
        return 1;
    }
    return 0;
}

int main()
{
    int T = read();
    while (T--)
    {
        n = read();
        for (int i = 1; i <= n; ++i)
        {
            num[i] = read();
        }
        while (!num[n] && n)
        {
            --n;
        }
        if (Check())
        {
            puts("Yes");
        }
        else
        {
            puts("No");
        }
    }
}

D. Fake Plastic Trees

贪心

不难发现叶子节点肯定需要被改一次,那么我们优先跑满叶子节点。叶子节点的祖先们如果加上这个值不够就得多搞一次,多搞的话也是优先选靠下的节点,如果权值超了的话直接改成它的最大值即可。

直接树形DP搞完事

点击查看代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <list>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int maxn = 2e5 + 10, maxe = 2e5 + 10, maxt = maxn * 600;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

char getFunc()
{
    char c;
    while (!isalpha(c = getchar()))
    {
    }
    return c;
}

struct Graph
{
    int head[maxn], len;
    int nxt[maxe], to[maxe];
    void Clear(int n)
    {
        for (int i = 1; i <= n; ++i)
        {
            head[i] = 0;
        }
        len = 0;
    }
    void Ins(int u, int v)
    {
        to[++len] = v;
        nxt[len] = head[u];
        head[u] = len;
    }
} G;

ll l[maxn], r[maxn];
ll f[maxn];

int ans = 0;

void DFS(int u, int fa)
{
    if (!G.head[u])
    {
        f[fa] += r[u];
        ++ans;
        return;
    }
    for (int i = G.head[u]; i; i = G.nxt[i])
    {
        int v = G.to[i];
        DFS(v, u);
    }
    ll val = min(f[u], r[u]);
    if (val < l[u])
    {
        ++ans;
        f[fa] += r[u];
    }
    else
    {
        f[fa] += val;
    }
}

int main()
{
    int T = read();
    while (T--)
    {
        int n = read();
        G.Clear(n);
        for (int i = 2; i <= n; ++i)
        {
            G.Ins(read(), i);
        }
        for (int i = 1; i <= n; ++i)
        {
            f[i] = 0;
            l[i] = read(), r[i] = read();
        }
        ans = 0;
        DFS(1, 0);
        printf("%d\n", ans);
    }
}

E. Keshi in Search of AmShZ

好像也是贪心)

我们建反图,在反图上搞

发现其实就是一个 Dijkstra 的变形

设 dis[u] 为节点 u 到达 n 的最小天数

deg[u] 为节点 u 在反图上的入度

我们更新的时候,选择当前 dis[u] 最小的 u 来枚举 u 所连接的每一个节点 v,每处理完一个 v 就 --deg[v],可以发现如果这样做从 u 点往它连接 v 点走所需要的代价是 deg[v]

然后松弛的时候比 dis[u] + deg[v] 和 dis[v] 的大小,跑 Dijkstra 即可。

点击查看代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <list>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int maxn = 2e5 + 10, maxe = 2e5 + 10, maxt = maxn * 600;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

char getFunc()
{
    char c;
    while (!isalpha(c = getchar()))
    {
    }
    return c;
}

struct Graph
{
    int head[maxn], len;
    int nxt[maxe], to[maxe];
    void Ins(int u, int v)
    {
        to[++len] = v;
        nxt[len] = head[u];
        head[u] = len;
    }
} G;

typedef pair<int, int> P;

int deg[maxn];
int dis[maxn];
bool vis[maxn];

int Dijkstra(int s)
{
    priority_queue<P, vector<P>, greater<P>> q;
    memset(dis, 0x3f, sizeof dis);
    dis[s] = 0;
    q.push(P(0, s));
    while (!q.empty())
    {
        int u = q.top().second;
        q.pop();
        if (vis[u])
        {
            continue;
        }
        vis[u] = 1;
        for (int i = G.head[u]; i; i = G.nxt[i])
        {
            int v = G.to[i];
            if (dis[u] + deg[v] < dis[v])
            {
                dis[v] = dis[u] + deg[v];
                q.push(P(dis[v], v)); 
            }
            --deg[v];
        }
    }
    return dis[1];
}

int main()
{
    int n = read(), m = read();
    for (int i = 1; i <= m; ++i)
    {
        int u = read(), v = read();
        G.Ins(v, u);
        ++deg[u];
    }
    printf("%d\n", Dijkstra(n));
}

F. Decinc Dividing

DP

好像和题解做法一样)那就粘题解吧

image

点击查看代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <list>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int maxn = 2e5 + 10, maxe = 2e5 + 10, maxt = maxn * 600;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

char getFunc()
{
    char c;
    while (!isalpha(c = getchar()))
    {
    }
    return c;
}

int num[maxn];
int fup[maxn], fdown[maxn];

int main()
{
    int n = read();
    ll ans = 0, res = n + 1;
    for (int i = 1; i <= n; ++i)
    {
        num[i] = read();
    }
    for (int i = n; i; --i)
    {
        fup[i] = 0x7fffffff;
        fdown[i] = -1;
        for (int j = i + 1; j <= n; ++j)
        {
            int up = -1, down = 0x7fffffff;
            if (fdown[j - 1] < num[j])
            {
                up = max(up, num[j - 1]);
            }
            if (num[j - 1] < num[j])
            {
                up = max(up, fup[j - 1]);
            }
            if (num[j] < fup[j - 1])
            {
                down = min(down, num[j - 1]);
            }
            if (num[j - 1] > num[j])
            {
                down = min(down, fdown[j - 1]);
            }
            if (up == fup[j] && down == fdown[j])
            {
                break;
            }
            fup[j] = up, fdown[j] = down;
            // printf("%d %d\n", up, down);
            if (up == -1 && down == 0x7fffffff)
            {
                res = j;
                break;
            }
        }
        ans += res - i;
    }
    printf("%lld\n", ans);
}

标签:10,typedef,800,int,CF,long,maxn,div,include
来源: https://www.cnblogs.com/eafoo/p/16397929.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有