Codeforces Round #197 (Div. 2)

来源:互联网 发布:excel 数据填表web 编辑:程序博客网 时间:2024/04/29 13:28

这次打cf第一次长分,比赛时做了A、B、C三道题,赛完了再做了D题。比赛开始两题很快就过了,一个7分钟一个30分钟,不过还是感觉英语着急,看题用了很长的时间。第三题就更蛋疼了,看了半个小时没看明白,代码也连交了两次WA,最后发现是修改代码的时候一个地方忘记删掉了,删了就直接A,不过也没时间了,第四题就没怎么看了。到后面测大数据的时候就坑了,第三题竟然Wrong answer on 34,看了下数据,确实贪心的思路有问题,不过在加个枚举就应该对了,改了一下AC。感觉有点遗憾,不过cf真心好玩,以后一定要坚持打,希望能分数越来越高大笑


A. Helpful Maths


题目链接:http://codeforces.com/problemset/problem/339/A

题目大意:给一串加法式子,其中的数字只会是1、2、3,需要输出数字为升序的加法式子

解题思路:sort排序

#include<iostream>#include<string>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define N 105int main (){    string s;    while(cin >> s)    {        int num[N];        int len = s.size(), t = 0;        for(int i = 0; i < len ; i++)        {            if(s[i] >= '1' && s[i] <= '3')                num[t++] = s[i]-'0';        }        sort(num, num+t);        for(int i = 0; i < t-1; i++)            printf("%d+", num[i]);        printf("%d\n",num[t-1]);    }    return 0;}




B. Xenia and Ringroad


题目链接:http://codeforces.com/contest/339/problem/B


题目大意:输入n, m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105).   n代表有n个房子,m代表要访问m个房子,注意规定只能按顺时针查找,输出要经过的路段长,每一个房子间的距离都为1,还需注意Xenia 可访问同一家房多次,样例2就是例子

解题思路:模拟

#include<stdio.h>#define N 100005int a[N];int main (){    int n, m;    int i, j;    while(scanf("%d %d", &n, &m) != EOF)    {        __int64 ans = 0;        for(i = 1; i <= m; i++)            scanf("%d", &a[i]);        ans = a[1] - 1;        for(i = 2; i <= m; i++)        {            if(a[i] == a[i-1]) continue;            if(a[i] > a[i-1])   {ans += a[i]-a[i-1]; continue;}            if(a[i] < a[i-1])   {ans += (n-a[i-1]+1) + a[i]-1; continue;}        }        printf("%I64d\n", ans);            }    return 0;}





C. Xenia and Weights


题目链接:http://codeforces.com/contest/339/problem/C

题目大意:有重量为1~10的砝码(数量无限多),你需要在天平上砝码,先放取一个砝码放左边,然后取一个砝码放右边,这样交替进行,并且规定每次前一个放的砝码不能和后一个放的砝码重量相同,且要保重这一次放砝码的一边的重量严格的大于另外一边。问能否按上述规定操作m次,若能,输出YES,并输出每一次放砝码的重量。若不能,输出NO.

解题思路:(有人用dp和搜索过了)当时比赛的时候用贪心的思路来写的,过了,不过被大数据砍了,跪在了Wrong answer on test34,一片贪心跪死人啊
test34数据:
Input
1110000000
4

Answer
YES
2 3 2 3
想一想确实,按贪心的思路肯定是从重量1开始放,输出的肯定是NO。不过如果枚举第一次放砝码的所以操作的话就可以过了,最多也就10个砝码,绝对不会超时~~~

#include<stdio.h>int ans[1005];int main (){    int s[15];    char num[15];    int i, j;    while(scanf("%s", num) != EOF)    {        int t = 0;        for( i = 0; i < 10; i++)        {            if(num[i] == '1')                 s[t++] = i+1;        }        int n, cnt;        scanf("%d", &n);                for(int k = 0; k < t; k++)        {            cnt=1;            int  l = 0, r = 0, flag = 0;             int lnum = -1, rnum = -1;            flag = 1;            l = s[k];            lnum = s[k];            ans[cnt++] = s[k];            for(j = 2; j <= n; j++)            {                if(!flag)  //flag = 0, 放左边                {                    flag = 1;                    for( i = 0; i < t; i++)                    {                        if(s[i] == rnum) continue;                        if(l+s[i] > r)                        {                            l += s[i];                            lnum = s[i];                            ans[cnt++] = s[i];                            break;                        }                                       }                    if(i == t) break;                            }                else                {                    flag = 0;                    for( i = 0; i < t; i++)                    {                        if(s[i] == lnum) continue;                        if(r+s[i] > l)                        {                            r += s[i];                            rnum = s[i];                            ans[cnt++] = s[i];                            break;                        }                                    }                        if(i == t) break;                }            }            if(j-1 == n) break;        }        if(j-1 == n)         {            printf("YES\n");            for(int i = 1; i < cnt-1; i++)              printf("%d ", ans[i]);            printf("%d\n", ans[cnt-1]);        }        else            printf("NO\n");    }    return 0;}







D. Xenia and Bit Operations

题目链接http://codeforces.com/problemset/problem/339/D

题目大意:有2^n个数,每两个数间先进行or操作合并为2^n-1个数,然后再每两个数之间进行xor操作合并为2^n-2个数,最后合并为一个数,问这一个数是什么?期间还有m个操作,每个操作输入p ,d两个数,代码将第p个数改为d。

解题思路:赤裸裸的线段树。


#include<stdio.h>#define N (1<<18)+10#define lson l,m,s<<1#define rson m+1,r,s<<1|1int tree[N<<2];int n, m, temp_n;void  PushUp(int s, int count){if((temp_n-count) % 2 != 0)//从底往上找是第几层,基数层进行or运算,偶数层进行xor运算tree[s] = tree[s<<1] | tree[s<<1|1];elsetree[s] = tree[s<<1] ^ tree[s<<1|1];}void updata(int p, int d, int l, int r, int  s, int count){if(l == r){tree[s] = d;return ;}int m = (l+r) >> 1;if(m >= p)updata(p,d,lson,count+1);elseupdata(p,d,rson,count+1);PushUp(s, count);}int main (){int i, j;scanf("%d %d", &n, &m);temp_n = n;n = 1 << n;for(i = 1; i <= n; i++){int num;scanf("%d", &num);updata(i, num, 1, n, 1, 0);}for(i = 1; i <= m; i++){int p, d;scanf("%d %d", &p, &d);updata(p, d, 1, n, 1, 0);printf("%d\n", tree[1]);}return 0;}


PS:线段树还很弱啊,一定要加油





E. Three Swaps

过几天再补上