Codeforces Round #612 (Div. 2)

Codeforces Round #612 (Div. 2)

B题:

题意:一横排是一张牌,如果满足任意三张牌可以组成的每一列有三张相同的牌或者有三张不同的牌就可以组成一副牌,问能组成多少副这样的牌,打乱顺序算一副。
题解:我们通过两张牌来匹配第三章牌的方式来确定。

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+505;
string arr[N];
map<string,int>mp;
int main()
{
    int n,k; cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>arr[i];
        mp[arr[i]]++;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            string tmp="";
            for(int m=0;m<k;m++){
                if(arr[i][m]==arr[j][m]) tmp+=arr[i][m];
                else{
                    if(arr[i][m]!='S'&&arr[j][m]!='S') tmp+='S';
                    else if(arr[i][m]!='T'&&arr[j][m]!='T') tmp+='T';
                    else tmp+='E';
                }
            }
            ans+=mp.count(tmp);
        }
    }
    cout<<ans/3<<endl;
}

C题:

题意:一串连续的灯泡,掉落下来了几个,现在需要我们重新弄上去。如果相邻的奇偶性不同那么我们答案就++。
题解:我们定义四个状态:当前的位置,可用的奇数,可用的偶数,当前位置是奇数还是偶数,我们奇数偶数不用单独枚举,如果我们知道我们当前位置前面的空位数,那么我用了多少奇数,另外的偶数个数一定是我们的空位数减去奇数个数。所以我们直接DP。

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e2+5;
int arr[N],b[N];
int f[105][105][105][3];
int main()
{
    int n; cin>>n;
    memset(f,inf,sizeof f);
    int odd=n-n/2,even=n/2,sum=0;
    for(int i=1;i<=n;i++){
        cin>>arr[i];
        if(arr[i]){
            if(arr[i]%2==0) even--;
            else odd--;
        }
        else sum++;
        b[i]=sum;
    }
    if(!arr[1]){
         f[1][1][0][1]=f[1][0][1][0]=0;
    }else{  
        if(arr[1]&1) f[1][0][0][1]=0;
        else f[1][0][0][0]=0;
    }
    for(int i=2;i<=n;i++){
        for(int j=0;j<=b[i];j++){
            int k=b[i]-j;
            if(arr[i]){
                if(arr[i]%2==0) f[i][j][k][0]=min(f[i-1][j][k][1]+1,f[i-1][j][k][0]);
                else f[i][j][k][1]=min(f[i-1][j][k][1],f[i-1][j][k][0]+1);
            } else{
                if(j) f[i][j][k][1]=min(f[i-1][j-1][k][1],f[i-1][j-1][k][0]+1);
                if(k) f[i][j][k][0]=min(f[i-1][j][k-1][1]+1,f[i-1][j][k-1][0]);
            }
        }
    }
    int ans;
    if(arr[n]){
        if(arr[n]&1) ans=f[n][odd][even][1];
        else ans=f[n][odd][even][0];
    }
    else ans=min(f[n][odd][even][1],f[n][odd][even][0]);
    cout<<ans<<endl;
}

D题:

题意:给n行,每行p,c,p代表这个而节点的父亲节点,c代表这个节点的子树中有多少个 a j a_j aj严格小于这个节点的 a i a_i ai
题解:我们从根节点开始遍历,一直搜索到叶子节点,先把叶子节点放在容器中,然后我们把每个非叶子节点插入到x=c[u]这个位置,这样就能保证前面有c[u]个节点的值比我们小(因为我们最后赋值的时候是升序赋值)。

#include<bits/stdc++.h>
using namespace std;
const int N=2e3+5;
vector<int> g[N];
int c[N],a[N];
vector<int> dfs(int u)
{
	vector<int> l;
	for(int i=0;i<g[u].size();i++){
		vector<int> d=dfs(g[u][i]);
		for(int j=0;j<d.size();j++) l.push_back(d[j]);
	}
	if(c[u]>l.size()) {cout<<"NO"<<endl; exit(0);}
	l.insert(l.begin()+c[u],u);
	return l;
}
int main()
{
	int n,rt; cin>>n;
	for(int i=1;i<=n;i++){
		int p; cin>>p>>c[i];
		g[p].push_back(i);
		if(!p) rt=i;
	}
	vector<int> ans=dfs(rt);
	int cnt=0;
	for(int i=0;i<ans.size();i++) a[ans[i]]=++cnt;
	cout<<"YES"<<endl;
	for(int i=1;i<=n;i++) cout<<a[i]<<' ';
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值