Codeforces Round #197 (Div. 2)

这次做了ABC三题,D题知道是线段树,但是没能在二十分钟内写出来,弱成渣了,看来果断以后还得刷刷线段树,C题最终测试的时候悲剧了,Wrong answer on test34。赛后稍微改了下A了,D题也A 了。总得来说毛病还很多,这次的题目除了最后一题,其他的真心不难,做出四道题目来应该来说很简单,但是我还是只做出两道来。分析一下原因,还是自己能力不够,手速不够快,看英语题目也看得很慢,然后还没看清楚题目意思就开始做题了,第三点是非常致命的,以后真心要注意,必须先看清楚题再下手,这样不仅没浪费时间,反而减少了很多时间,因为没看清楚题可能做题方向就是错的,下次一定得注意!打CF还是蛮好玩的,两个小时相当的刺激,以后争取每场都参加,希望rating早日变紫咬牙切齿(这次rating终于没下降了。。。涨了41。。。)

A. Helpful Maths

题目大意

给定一个只含+号的表达式,要求你把被加数按从小到大的顺序排序,然后再把表达式输出

题解

顺便怎么写。。。

代码:

#include<iostream>

#include<set>

#include<algorithm>

#include<cstdio>

#include<cstring>

#include<string>

#include<vector>

using namespace std;

int main()

{

    vector<char>iset;

    string s;

    cin>>s;

    iset.push_back(s[0]);

    for(int i=1; i<s.size(); i++)

        if(s[i]!='+')

            iset.push_back(s[i]);

    int len=iset.size();

    sort(iset.begin(),iset.end());

    printf("%c",iset[0]);

    for(int i=1; i<len; i++)

        printf("+%c",iset[i]);

    printf("\n");

    return 0;

}

 

B. Xenia and Ringroad

题目大意

有n个房子,它们分布是环状的,顺时针依次编号为1 ~n。有m个任务,对于第i个任务会给出一个数a[i],要求你从编号为1的房子开始,按顺时针依次走到编号为a[1],a[2],a[3]……a[i]的房子,从一个房子移动的到相邻的房子需要一个单位时间,问你完成所有的任务需要花费最少的时间是多少

题解

依次计数即可,如果a[i-1]<=a[i],时间花费为a[i]-a[i-1],如果a[i-1]>a[i],则时间花费为n-a[i-1]+a[i]

代码:

#include<iostream>

#include<algorithm>

#include<cstring>

#include<vector>

using namespace std;

#define MAXN 100005

int main()

{

    long long  ans,m,n,last,p;

    cin>>n>>m;

    ans=0;

    last=1;

    for(int i=1;i<=m;i++)

    {

        cin>>p;

        if(last<=p)

        ans+=p-last;

        else

        ans+=n-last+p;

        last=p;

    }

    cout<<ans<<endl;

    return 0;

}

 

C. Xenia and Weights

题目大意

有一些重量为1~10之间的砝码(数量无限多),给你一个天平,要求你第一次选取一个砝码放在左盘,第二次选取一个砝码放在右盘,这样依次交替下去,这里有两个要求,就是在把某个砝码放在一个盘中之后它的砝码总重量必须大于另外一个盘,并且放的那个砝码的重量不能和前一次放的砝码重量相同,问你这样能否进行m次,如果可以就输出YES,并按顺序输出选择的砝码重量,否则输出NO

题解

我当时写的是贪心,最终测试的时候是Wrong answer on test34,这组数据挂了好多人!!!

错在这组数据上:

Input

1110000000

4

Output

NO

Answer

YES

2 3 2 3
我是从第一次开始,每次选取一个尽量小的符合要求的砝码放进盘里,这样一直进行下去。显然,每次选取一个小的砝码并不比选一个更大的砝码结果更糟糕,不过在WA在上面那组数据上了,我
这样做会这样做出选择,1 2 3 然后就无法在进行下去了,这样就导致错误了,其实我们只要枚举第一个盘放的砝码,这样就没问题了~~~大部分人写的都是DFS,我当时看见m=1000,就没敢写。。

代码:

#include<iostream>

#include<algorithm>

#include<cstring>

#include<cstdio>

#include<string>

using namespace std;

int a[15],b[1005];

int main()

{

    string s;

    int n=0,m,i,t;

    bool flag=false;

    cin>>s>>m;

    for( i=0; i<s.size(); i++)

        if(s[i]=='1') a[n++]=i+1;

    for(int k=0; k<n; k++)

    {

        flag=false;

        int lsum=0,last,rsum=0;

        t=0;

        lsum+=a[k];

        last=a[k];

        b[t++]=a[k];

        for(int j=1; j<m; j++)

        {

            if(j%2==0)

            {

                for(i=0; i<n; i++)

                    if(lsum+a[i]>rsum&&a[i]!=last)

                    {

                        lsum+=a[i];

                        last=a[i];

                        b[t++]=a[i];

                        break;

                    }

                if(i>=n)

                {

                    flag=true;

                    break;

                }

            }

            else

            {

                for( i=0; i<n; i++)

                    if(rsum+a[i]>lsum&&a[i]!=last)

                    {

                        rsum+=a[i];

                        last=a[i];

                        b[t++]=a[i];

                        break;

                    }

                if(i>=n)

                {

                    flag=true;

                    break;

                }

            }

        }

        if(!flag)

        {

            puts("YES");

            for(i=0; i<t; i++)

                printf("%d ",b[i]);

            printf("\n");

            break;

        }

    }

    if(flag||n==0)

        puts("NO");

    return 0;

}

 

D. Xenia and Bit Operations

题目大意

给定一个序列a[1],a[2],a[3]……a[2^n]

可以对其进行下面这种操作:

把 a[p]的值修改为b

然后查询V值,V值是这样的定义的:

第一次时,第2*i项与第2*i-1项位或,剩余2^(n-1)项

第二次时,第2*i项与第2*i-1项异或,剩余2^(n-2)项

异或和位或交替执行

这样依次进行下去,直到合并为一个数为止,这个数就是V的值

题解

裸线段树啊,就是单点修改这个操作,尼玛当时居然没写出来悲伤,赛后改了一个小时,然后发现是手残把递归深度标记这个变量进行递归的时候++了,改成+1就A了。。。。操蛋啊

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

#define lson l,m,s<<1

#define rson m+1,r,s<<1|1

const int MAXN =(1<<18)+5;

int sumv[MAXN<<2];

int n;

void PushUp(int s,int cnt)

{

    if((n-cnt)&1)

        sumv[s]=(sumv[s<<1])|(sumv[s<<1|1]);

    else

        sumv[s]=(sumv[s<<1])^(sumv[s<<1|1]);

}

void update(int p,int d,int l,int r,int s,int cnt)

{

    if(l==r)

    {

        sumv[s]=d;

        return;

    }

    int m=(l+r)>>1;

    if(p<=m) update(p,d,lson,cnt+1);

    else

        update(p,d,rson,cnt+1);

    PushUp(s,cnt);

}

int main(void)

{

    int m;

    scanf("%d%d",&n,&m);

    for(int i=0;i<(1<<n);i++)

    {

        int a;

        scanf("%d",&a);

        update(i+1,a,1,(1<<n),1,0);

    }

    while(m--)

    {

        int p,b;

        scanf("%d%d",&p,&b);

        update(p,b,1,(1<<n),1,0);

        printf("%d\n",sumv[1]);

    }

    return 0;

}

 

E. Three Swaps

还没看题,写完再补题解

 

你可能感兴趣的:(codeforces)