Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1)

来源:互联网 发布:字符串拷贝到数组 编辑:程序博客网 时间:2024/04/28 10:25

比赛链接

A. Bear and Big Brother

题意:起初给你两个数a,b,每经过一天a变为原来的3倍,b变为原来的2倍,问多少天后a将大于b

#include<vector>#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<cmath>const int max_n=200005;using namespace std;long long int a,b;int main(){int z=0; cin>>a>>b; if(a==b){    cout<<1<<endl;    return 0; } else while(a<=b){    a=a*3;    b=b*2;    z++;     }     cout<<z<<endl;}


B. Bear and Friendship Condition

题意:已知n个人,标号1到n,给出m组朋友关系,同时如果给出a,b是朋友关系,b,c是朋友关系,则a,c也必须给出是朋友关系,问给的m组关系是否正确

由于朋友关系具有传递性,故如果一群朋友圈有x个人,则每个成员具有(x-1)条关系,整个圈子有(x-1)*x/2条不重复的关系

自己写的是并查集,将一个朋友圈的人数和关系条数记录在根节点,对每一组关系中的编号,如果他们的根相同,则将根的关系条数加1即可,如果根不同则将这两个成员的根的关系条数相加,以及成员数相加存入合并后的根节点内,最后对于所有的根节点判断  关系条数=(成员数-1)*成员数/2是否成立。

注意:(x-1)*x/2会爆int 因为这个查了半天

#include<vector>#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<cmath>using namespace std;const int max_n=350004;long long int par[max_n],a[max_n],b[max_n],z[max_n];long long int find0(long long int x){ if(par[x]==x)    return x; else return par[x]=find0(par[x]);}int main(){long long int n,m;cin>>n>>m;for(int i=1;i<=n;i++){   par[i]=i;}for(int i=0;i<m;i++){    long long int x,y;     cin>>x>>y;     par[find0(x)]=find0(y);     a[x]++;     a[y]++;    }for(int i=1;i<=n;i++)    z[find0(i)]+=1;for(int i=1;i<=n;i++){    if(a[i]!=z[find0(i)]-1){        cout<<"NO"<<endl;        return 0;    }}cout<<"YES"<<endl;}

其实套并查集模板那么麻烦,依然是并查集的思想,不用判断根数以免爆int,判断含有n个人的圈子每个成员关系条数是否都为(n-1)

#include<vector>#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<cmath>using namespace std;const int max_n=350004;long long int par[max_n],a[max_n],b[max_n],z[max_n];long long int find0(long long int x){ if(par[x]==x)    return x; else return par[x]=find0(par[x]);}int main(){long long int n,m;cin>>n>>m;for(int i=1;i<=n;i++){   par[i]=i;}for(int i=0;i<m;i++){    long long int x,y;     cin>>x>>y;     par[find0(x)]=find0(y);     a[x]++;     a[y]++;    }for(int i=1;i<=n;i++)    z[find0(i)]+=1;for(int i=1;i<=n;i++){    if(a[i]!=z[find0(i)]-1){        cout<<"NO"<<endl;        return 0;    }}cout<<"YES"<<endl;}

当然这个也可以用dfs写,搞个数组标记一下就好了,但是自己憋了半天没写出来,看了别人的代码发现自己好傻逼

#include<vector>#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<cmath>using namespace std;const int max_n=150004;vector<int> v[max_n];int cnt[max_n],used[max_n],n,m,t,z[max_n];void dfs(int k){used[k]=1;cnt[k]=t;z[t]++;for(int i=0;i<v[k].size();i++){    if(!used[v[k][i]])        dfs(v[k][i]);}}int main(){cin>>n>>m;for(int i=0;i<m;i++){    int x,y;    cin>>x>>y;    v[x].push_back(y);    v[y].push_back(x);}for(int i=1;i<=n;i++){    if(!used[i]){        t++;        dfs(i);    }}for(int i=1;i<=n;i++){    if(v[i].size()!=z[cnt[i]]-1){        cout<<"NO"<<endl;        return 0;    }}cout<<"YES"<<endl;}

C. Bear and Different Names

军队里面的人名不可重复,给你n个人名,以及k和n-k+1个描述,i从1到n-k+1,对于从i开始的连续k个名字是否合法已知,让你输出这些名字(自己构造),要求名字第一个大写,其他为小写,名字长度范围为1到10

个人感觉比B题简单,就是构造和贪心的思想,从后到前判断,人名我是打表的,因为n比较小

#include<vector>#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<cmath>#include<string>using namespace std;string s[100]={"Q","W","E","R","T","Y","U","I","O","P","A","S","D","F","G","H","J","K","L","Z","X","C","V","B","N","M","Aa","Qq","Ww","Ee","Rr","Tt","Yy","Uu","Oo","Ooo","Ooooo","Mm","Mmmm","Hhh","Hh","Vv","Vvv","Vvvvv","Pppp","Sd","Sa","Sc","Sq","Hs","Kj","Kkkk","Klllll"};string ans[55];using namespace std;int main(){int n,k,p[55];cin>>n>>k;for(int i=1;i<=n-k+1;i++){    string a;    cin>>a;    if(a=="NO")        p[i]=1;    else p[i]=0;}int i=n;while(i>n-k+1){    ans[i]=s[i];    i--;}while(i>=1){    if(p[i]==0)        ans[i]=s[i];    else ans[i]=ans[i+k-1];    i--;}for(int i=1;i<n;i++)    cout<<ans[i]<<" ";cout<<ans[n]<<endl;}

D和E等姿势涨了再回来补QAQ

总结:本次cf竟然就过了一道题,刚上的蓝又掉到绿了,菜啊,主要看到B,感觉是个DFS就虚了,一个简单DFS窝憋半天可能都憋不出来,C题压根没看,40分钟就弃疗了,犯了大忌啊,改!改!改!

-741610 → 1536Became Specialist




0 0
原创粉丝点击