首页 > 代码库 > codeforces round #418 div 2

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\n", 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\n", tot);
    return 0;
}
View Code

 

codeforces round #418 div 2