Codeforces Round #635 (Div. 2) 补题


A. Ichihime and Triangle
输出以a c c为三条边的等边三角形即可

代码
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    read(q);
    while(q--){
        int a,b,c,d;
        read(a),read(b),read(c),read(d);
        cout<<a<<" "<<c<<" "<<c<<"\n";
    }
 	return 0;
}
 

B. Kana and Dragon Quest game
在x大于20时,x/2+10的操作可以使x减小。所以在x大于二十时,对x实行第一种操作,之后再判断第二种操作能否使x变的小于0

代码
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    read(q);
    while(q--){
        int x,n,m;
        cin>>x>>n>>m;
        while((x/2+10)<x&&n){
            x=x/2+10;
            n--;
        }
        if(x-m*10<=0) printf("YES\n");
        else printf("NO\n");
    }
 	return 0;
}
 

C. Linova and Kingdom
最开始的想法是先选择完最深层的叶子节点(并不正确),之后选择第二深的叶子节点。可以发现在选择一个节点后,他的所有子孙对答案的贡献都会减一,于是就可以想到,每个节点对答案的贡献就是深度-子孙数(节点1深度是0),那么统计每个节点的深度-子孙数的值,排序后选取前k大的数就可以。

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
vector<int> deep,siz;
vector<vector<int> > node;
void dfs(int x,int p){
    for(auto i:node[x]){
        if(i==p) continue;
        deep[i]=deep[x]+1;
        dfs(i,x);
        siz[x]+=siz[i]+1;
    }
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int n,k;
    read(n),read(k);
    deep.resize(n+1);
    node.resize(n+1);
    siz.resize(n+1);
    for(int i=1;i<n;i++){
        int a,b;
        read(a),read(b);
        node[a].push_back(b);
        node[b].push_back(a);
    }
    dfs(1,-1);
    vector<int> dp;
    for(int i=1;i<=n;i++){
        dp.push_back(deep[i]-siz[i]);
    }
    sort(dp.begin(),dp.end());
    ll ans=0;
    for(int i=1;i<=k;i++){
        ans+=dp[n-i];
    }
    cout<<ans;
 	return 0;
}
 

D. Xenia and Colorful Gems
比赛时的想法是遍历a数组,遍历到元素x时,二分搜索选取b和c里面与x最接近的元素p和q,更新ans的值,因为担心这样不能得到最小值于是把b里面比p小的数和比p大的数,c里面比q小的数和比q大的数也计算一遍,结果交上去wa了,于是又加上了分别固定b,c重复上述操作,结果tle了。。。赛后发现思路是可以的,但是更新ans时进行了太多重复操作,可以优化写法。

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
vector<int> deep,siz;
vector<vector<int> > node;
void dfs(int x,int p){
    for(auto i:node[x]){
        if(i==p) continue;
        deep[i]=deep[x]+1;
        dfs(i,x);
        siz[x]+=siz[i]+1;
    }
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    read(q);
    while(q--){
        int sz[3];
        cin>>sz[0]>>sz[1]>>sz[2];
        vector<int> a[3];
        for(int i=0;i<3;i++){
            a[i].resize(sz[i]);
            for(int j=0;j<sz[i];j++) cin>>a[i][j];
            sort(a[i].begin(),a[i].end());
        }
        ll ans=(ll)4e18+10;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                for(int k=0;k<3;k++){
                    if(i==j||i==k||j==k) continue;
                    for(int x:a[i]){
                        auto _p=lower_bound(a[j].begin(),a[j].end(),x);
                        auto _q=upper_bound(a[k].begin(),a[k].end(),x);
                        if(_p!=a[j].end()&&_q!=a[k].begin()){
                            int p=*_p;
                            _q--;
                            int q=*_q;
                            ans=min(ans,1ll*(p-q)*(p-q)+1ll*(p-x)*(p-x)+1ll*(q-x)*(q-x));
                        }
                    }
                }
        cout<<ans<<"\n";
    }
 	return 0;
}
 

E. Kaavi and Magic Spell
采用dp,学习了评论区的做法。最后要得到的字符串是a,dp[l][r]代表使用s中前r-l个字符(相当于前r-l次操作之后)构成a中[l,r)这一段的所有操作方法。比如t是abcd,那么dp[2][5]就代表s经过前3次操作得到cd*的方法数,*是因为得到的a字符串只要前缀满足t就可以,第4个可以是任意字符。
可以得出状态转移方程当更新到dp[l][r]时,如果l不超过m,并且s[r-l-1]=t[l],也就是目前s第一个字符可以匹配到a的左端,那么有dp[l][r]+=dp[l+1][r],如果l大于m,因为a超过t的部分可以任意匹配,所以也可以有这样的转移方程。当r<=m时,如果s[r-l-1]=t[r-1](r-1是因为右边是开区间),说明目前s第一个字符可以与a的右端匹配,有转移方程dp[l][r]+=dp[l][r-1],如果r大于m,也有这样的转移方程。

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
const int mod=998244353;
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    string s,t;
    cin>>s>>t;
    int n=s.size(),m=t.size();
    vector<vector<ll> > dp(n+1,vector<ll>(n+1));
    for(int i=0;i<=n;i++) dp[i][i]=1;
    for(int len=1;len<=n;len++){
        char c=s[len-1];
        for(int l=0;l+len<=n;l++){
            int r=l+len;
            if(l>=m||t[l]==c){
                dp[l][r]+=dp[l+1][r];
                dp[l][r]%=mod;
            }
            if(r>m||t[r-1]==c){
                dp[l][r]+=dp[l][r-1];
                dp[l][r]%=mod;
            }
        }
    }
    ll ans=0;
    for(int i=m;i<=n;i++){
        ans+=dp[0][i];
        ans%=mod;
    }
    cout<<ans;
 	return 0;
}
 

F. Yui and Mahjong Set
还没看懂

代码
代码

猜你喜欢

转载自www.cnblogs.com/DinoMax/p/12716245.html