• codeforces round #418 div 2


    这场是吕队长的orz

    A:如果k>1 那么肯定是可以的 因为两个数必然有大小关系 小的放在大的前面就行了 k=1 填进去判一下就行了

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010;
    int n, k, pos;
    int a[N], b[N];
    int main()
    {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; ++i) 
        {
            scanf("%d", &a[i]);
            if(a[i] == 0) pos = i;
        }
        for(int i = 1; i <= k; ++i) 
            scanf("%d", &b[i]);
        if(k > 1)
        {
            puts("Yes");
            return 0;
        }
        a[pos] = b[1];
        for(int i = 1; i <= n; ++i)
        {
            for(int j = i + 1; j <= n; ++j) 
                if(a[i] >= a[j])
                {
                    puts("Yes");
                    return 0;
                }
        } 
        puts("No");
        return 0;
    }
    View Code

    B:这道题略坑wa了三发

    两个序列肯定有一个位置不同 这是题目给出的条件 也就是说不用判两个序列相同的情况

    题目要求构造出的排列和a b各有且仅有一个位置不同 那么这样说明a和b至多有两个位置不同 至少一个位置不同

    如果一个位置不同 那么找出一个没选过且和ab该位均不同的数字填上

    两个位置不同 对于这两个位置 肯定一个对应填上a 一个对应填上b 那么就是要看两种中哪种合法

    先将一种情况带入。扫描判一下,不成立就换另一种情况。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010;
    int n;
    int a[N], b[N], used[N], p[N], pos[N];
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        for(int i = 1; i <= n; ++i)
            scanf("%d", &b[i]);
        for(int i = 1; i <= n; ++i)
        {
            p[i] = a[i];
            if(a[i] != b[i])
                pos[++pos[0]] = i;
            else used[a[i]] = 1;
        }
        if(pos[0] == 1)
        {
            for(int i = 1; i <= n; ++i) 
                if(!used[i])
                p[pos[1]] = i;
            for(int i = 1; i <= n; ++i)
                printf("%d ", p[i]);
            return 0;
        }
        p[pos[1]] = b[pos[1]];
        p[pos[2]] = a[pos[2]];
        memset(used, 0, sizeof(used));
        for(int i = 1; i <= n; ++i)
        {
            if(used[p[i]]) 
            {
                p[pos[1]] = a[pos[1]];
                p[pos[2]] = b[pos[2]];
                break;
            }
            used[p[i]] = 1;
        }
        for(int i = 1; i <= n; ++i)
            printf("%d ", p[i]);
        return 0;
    }
    View Code

    C:这道题忘记清空数组wa了4发罚时爆炸。。。1小时才做出来。。。

    感觉很像一个dp,实际上也是一个dp。

    dp[i][j][c]表示i位置至多刷了j次,这个位置刷后为c的最长序列

    容易得出 如果这位不等于c dp[i][j][c]=dp[i-1][j-1][c]+1 否则等于dp[i-1][j][c]。用mx[j][c]记录刷了至多j次最长的序列的长度

    那么询问就是O(1)的了。

    mx[j][c]要用mx[j-1][c]更新 因为我的程序原先j是到i的,所以当j>1时dp[i][j][c]就是0,不能更新以后。

    这样写也可以。。。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1510;
    int n, q, k;
    char s[N];
    int dp[2][N][27], mx[N][27];
    int main()
    {
        scanf("%d", &n);
        scanf("%s", s + 1);
        for(int i = 1; i <= n; ++i)
        {
            k ^= 1;
            memset(dp[k], 0, sizeof(dp[k]));
            for(int c = 0; c < 26; ++c)
            {
                for(int j = 0; j <= n; ++j)
                {
                    if(c != s[i] - 'a') 
                    {
                        if(j) dp[k][j][c] = dp[k ^ 1][j - 1][c] + 1;
                    }
                    else dp[k][j][c] = dp[k ^ 1][j][c] + 1;
                    mx[j][c] = max(mx[j][c], dp[k][j][c]);
                }
            }
        }
        scanf("%d", &q);
        while(q--)
        {
            int m; char s[10]; scanf("%d%s", &m, s);
            printf("%d
    ", mx[m][s[0] - 'a']);
        }
        return 0;
    }
    View Code

    D:比赛时以为是圆的异或面积并,于是就gg了。。。

    我们可以这样讨论:对于一个圆,当他被覆盖的次数是0或者%2=1时才加上他的面积。

    为什么呢?我们不妨这么想:对于一些圆,他们互相包含,也就是说他们是一堆圆套着一堆圆。

    那么这里运用贪心的思想:第一个圆最大,我们要加上,放到第一组,第二个圆第二大,我们也要加上,放到第二组。但是到第三个圆,无论放哪里,都得减去,于是我们放到第一组。

    第四个圆,放到第一组的话,就可以加上,于是放到第一组,以此类推。于是我们就按着这个思路贪心,记录每个圆呗覆盖次数,然后计算面积就行了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010;
    const double pi = 3.1415926535898;
    struct data {
        double x, y, r;
    } x[N];
    int n;
    double tot;
    double sqr(double x)
    {
        return x * x;
    }
    double dis(double x1, double x2, double y1, double y2)
    {
        return sqrt(sqr(x1 - x2) + sqr(y1 - y2));
    }
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
            scanf("%lf%lf%lf", &x[i].x, &x[i].y, &x[i].r);
        for(int i = 1; i <= n; ++i) 
        {    
            int cnt = 0;
            for(int j = 1; j <= n; ++j) if(j != i)
                if(dis(x[i].x , x[j].x, x[i].y, x[j].y) <= x[j].r - x[i].r)
                    ++cnt;
            if(cnt == 0 || cnt % 2 == 1) tot += x[i].r * x[i].r * pi;
            else tot -= x[i].r * x[i].r * pi; 
        }
        printf("%.10f
    ", tot);
        return 0;
    }
    View Code
  • 相关阅读:
    网络流初步——增广路算法(EK)模板
    求大组合数
    RMQ问题
    欧拉函数
    [LintCode] Minimum Path Sum
    [LintCode] Unique Paths II
    [LintCode] Unique Paths
    [LintCode] Flip Bits
    [LintCode] O(1) Check Power of 2
    [LintCode] Count 1 in Binary
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6959801.html
Copyright © 2020-2023  润新知