Codeforces Round #197 (Div. 2)

这次打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 105
int 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 100005
int 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|1
int 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];
	else
		tree[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);
	else
		updata(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

过几天再补上








你可能感兴趣的:(codeforces)