Codeforces Round #403 (Div. 2)(A-E 未完)

来源:互联网 发布:福州seo基础培训班 编辑:程序博客网 时间:2024/05/17 01:54

A. Andryusha and Socks

题意:现在有n对数字,每次拿出一个数字到桌子上,如果这个数字以前就出现过,就把当前数字和以前数字都都拿走,问桌子上最多有多少种袜子
思路:简单模拟

代码:

#include<bits/stdc++.h>using namespace std;int n;int a[100010];int main(){    int ans=0;    int maxn=-1;    scanf("%d",&n);    for(int i=0;i<2*n;i++)    {        int temp;        scanf("%d",&temp);        if(a[temp]==0)        {            a[temp]++;            ans++;            maxn=max(maxn,ans);        }        else        {            ans--;        }    }    printf("%d\n",maxn);}

B. The Meeting Place Cannot Be Changed

题意:现在n个人站在一条路上,每个人都有一个坐标和一个速度,现在要让所有人跑到一个点上,问所需最小时间是多少
思路:二分,二分时间,看该时间能不能让所有人跑到某个点,浮点数二分用for循环100次即可提炼精度,不得不说浮点数二分比整数二分好写多了= =

代码:

#include<bits/stdc++.h>using namespace std;struct poi{    int x;    int s;}a[60100];bool cmp(poi w,poi e){    return w.x<e.x;}int n;bool judge(double time){    double len=1.0*a[0].x+1.0*time*a[0].s;    for(int i=1;i<n;i++)    {        if(a[i].x<len)        {            len=min(len,1.0*a[i].x+1.0*time*a[i].s);        }        else        {            if(1.0*a[i].x-1.0*time*a[i].s>len)                return false;        }    }    return true;}int main(){    scanf("%d",&n);    for(int i=0;i<n;i++)        scanf("%d",&a[i].x);    for(int i=0;i<n;i++)        scanf("%d",&a[i].s);    sort(a,a+n,cmp);    double l=0;double r=1000000000;    for(int i=0;i<100;i++)    {        double mid=(l+r)/2;        if(judge(mid))            r=mid;        else            l=mid;    }    printf("%.7f\n",(l+r)/2.0);}

C. Andryusha and Colored Balloons

题意:给你一个图,任意点和它所连的点,这些点之间的任意两点的颜色不能相同,问最少要几种颜色,并给出配色方案
思路:DFS,DFS的时候一边更新最少颜色数,一边染色,在DFS的时候,记录该点的颜色和其之前一个点的颜色会好写一些

代码:

#include<bits/stdc++.h>using namespace std;int n;vector<int> q[200010];int b[200010];int ans=0;void dfs(int now,int fa,int bef,int me){    int col=1;    ans=max(ans,(int)q[now].size()+1);    for(int i=0;i<q[now].size();i++)    {        if(q[now][i]!=fa)        {            while(col==bef||col==me)            col++;                b[q[now][i]]=col;            col++;            dfs(q[now][i],now,me,col-1);        }    }    return ;}int main(){    scanf("%d",&n);    for(int i=0;i<n-1;i++)    {        int tempa,tempb;        scanf("%d%d",&tempa,&tempb);        q[tempa].push_back(tempb);        q[tempb].push_back(tempa);    }    b[1]=1;    dfs(1,-1,-1,1);    printf("%d\n",ans);    for(int i=1;i<=n;i++)    {        if(i!=1) printf(" ");        printf("%d",b[i]);    }    puts("");}

D. Innokenty and a Football League

题意:现在有N个队伍,每个队伍的全名有两个部分,现在有给每个队伍起简称,第一种简称是第一个名字的前三位,第二种是第第一个名字的前两位加第二个名字的第一位。每个队伍都想优先使用第一种,但是如果若干个队伍的第一种相同了,那么他们只能使用第二种,如果一个队伍的第一种被占用了,那它也只能使用第二种了
思路:map容器,如果有的队伍第一种名称相同,那么他们都别无选择的使用第二种,如果有个队伍的第一个名字被用了,那他只能用第二种,如果第二个被用了,那他只能用第一种,如果都没有被使用,那就使用第一种。这个题的坑就在,即使两个队伍的第一个名字没有出现重复,也是可能相互制约的,要考虑好优先级才能AC

代码:

#include<bits/stdc++.h>using namespace std;map<int,int> mp;//只是用来查看当前字符串以前有没有检查过map<int,int> mpp;//判断某个名字是否冲突char a[1010][2][25];//储存原数组串char ans[1010][3];//储存答案bool did[1010];//判断是否已经有答案了int name(int a,int b,int c){return a*10000+b*100+c;}//hash名字int main(){    int n;    scanf("%d",&n);    bool judge=true;    for(int i=0;i<n;i++) scanf("%s%s",a[i][0],a[i][1]);    for(int i=0;i<n;i++)//用来看当第一种名字相同时,第二种名字是否出现冲突    {        int temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][0][2]-'a');        if(mp[temp]>=1)            continue;        else        {            mp[temp]=1;            for(int j=i+1;j<n;j++)            {                int tempa=name(a[j][0][0]-'a',a[j][0][1]-'a',a[j][0][2]-'a');                if(tempa==temp)                {                    mp[temp]=2;                    for(int k=i;k<n;k++)                    {                        int tempb=name(a[k][0][0]-'a',a[k][0][1]-'a',a[k][1][0]-'a');                        int tempc=name(a[k][0][0]-'a',a[k][0][1]-'a',a[k][0][2]-'a');                        if(tempc==temp){                            mpp[tempb]++;                            did[k]=true;                            ans[k][0]=a[k][0][0]; ans[k][1]=a[k][0][1]; ans[k][2]=a[k][1][0];                            if(mpp[tempb]==2){                                judge=false;                                break;                            }                        }                    }                    break;                }            }        }    }    if(judge)    {        bool change=false;        for(int i=0;;i++)//当某个队伍别无选择时,就能确定他的队名,不断循环到没有更新为止        {            if(i==n)            {                i=0;                if(change==0) break;                change=false;            }            int temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][0][2]-'a');            if(mp[temp]==1&&did[i]==0)//第一种队名没重复且名字不确定            {                if(mpp[temp]==1)//第一个名字被用了                {                    temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][1][0]-'a');                    if(mpp[temp]==1)//第二个也被用了就没办法了                    {                        judge=false;                        break;                    }                    else{                        change=true;                        ans[i][0]=a[i][0][0]; ans[i][1]=a[i][0][1];ans[i][2]=a[i][1][0];                        did[i]=true;                        mpp[temp]++;                    }                }                else                {                    temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][1][0]-'a');                    if(mpp[temp]==1)//第二个被用了就只能用第一个了                    {                        change=true;                        temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][0][2]-'a');                        ans[i][0]=a[i][0][0]; ans[i][1]=a[i][0][1]; ans[i][2]=a[i][0][2];                        did[i]=true;                        mpp[temp]++;                    }                }            }        }        if(judge)        {            printf("YES\n");            for(int i=0;i<n;i++)                if(did[i])                    printf("%c%c%c\n",ans[i][0],ans[i][1],ans[i][2]);                else                    printf("%c%c%c\n",a[i][0][0],a[i][0][1],a[i][0][2]);        }        else            printf("NO\n");    }    else        printf("NO\n");}

E. Underground Lab

题意:有n个点,m个边,现在有k个起点,每个点最多走 (2n)/k个点,保证有解,求每个点的行动轨迹
思路:DFS,这个题的关键就是要看懂那个向上取整。。。发现是个向上取整的话,就会发现,每个点就算跑两次都能把这个图跑完,那么只要DFS一次,记录下路径,然后分k次输出就好了。。。只能说这个题如果能看懂那个向上取整就毫无难度了,然而我看了题解才看懂。。。。

代码:

#include<bits/stdc++.h>using namespace std;const int maxn=2e5+10;vector<int> a[maxn];bool did[maxn];int ans[maxn*2];int cnt=0;void dfs(int now){    did[now]=true;    ans[cnt++]=now;    for(int i=0;i<a[now].size();i++)    {        if(!did[a[now][i]]){            dfs(a[now][i]);            ans[cnt++]=now;        }    }}int main(){    int n,m,k;    scanf("%d%d%d",&n,&m,&k);    for(int i=0,v,u;i<m;i++)    {        scanf("%d%d",&v,&u);        a[v].push_back(u);        a[u].push_back(v);    }    int step=(2*n+k-1)/k;    dfs(1);cnt--;    for(int i=0;i<k;i++)    {        int l=min(step,cnt+1);        if(l==0)        {            printf("1 1\n");            continue;        }        printf("%d",l);        for(int j=0;j<l&&cnt>=0;j++,cnt--)            printf(" %d",ans[cnt]);        puts("");    }}