Codeforces Round #547 (Div. 3) 全部题解

http://codeforces.com/contest/1141

这次div3没打,下来做了一下也不是挺难的;

A. Game 23

题意:给出两个数n和m,问n几步可以变到m,其中只可以乘2或者乘3

解法:直接dfs

#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
ll n,m;
bool flag=false;
void dfs(int x,int s)
{
    if(flag||x>m)
        return;
    if(x==m)
    {
        flag=true;
        cout<<s<<endl;
        return;
    }
    dfs(x*2,s+1);
    dfs(x*3,s+1);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    dfs(n,0);
    if(!flag)
        cout<<-1<<endl;
    return 0;
}

B. Maximal Continuous Rest

题意:找到连续1的最长长度,注意可以是一个圈可以循环;

解法:直接模拟即可,没什么说的

#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m;
int a[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    int l=0,r=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i]!=1)
            break;
        l++;
    }
    for(int i=n;i>=1;i--)
    {
        if(a[i]!=1)
            break;
        r++;
    }
    int tmp=0,ans=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==1)
            tmp++;
        else
        {
            ans=max(tmp,ans);
            tmp=0;
        }
    }
    cout<<max(l+r,ans)<<endl;
    return 0;
}

C. Polycarp Restores Permutation

题意:给n-1个数为q,qi=p(i+1)-pi,根据q求出p, 求不出时为-1,注意,p为一个排列。

做法:首先假设p1为一个随便的值不会超过范围就行,然依次推出来,在找到最小值以此基础上变到1,全部加上一个数。

#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m;
int a[N],b[N],c[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n-1;i++)
        cin>>a[i];
    b[1]=0;c[1]=0;
    c[0]=-2*N;
    for(int i=2;i<=n;i++)
    {
        b[i]=a[i-1]+b[i-1];
        c[i]=b[i];
    }
    int add=2*N;
    sort(c+1,c+n+1);
    c[0]=c[1]-1;
    for(int i=1;i<=n;i++)
    {
        if(c[i]-c[i-1]!=1)
        {
            cout<<"-1"<<endl;
            return 0;
        }
        add=min(add,b[i]);
    }
    for(int i=1;i<=n;i++)
        cout<<b[i]-(add-1)<<" ";
    cout<<endl;
    return 0;
}

D. Colored Boots

题意:给两个字符串a和b,每个字符表示一个靴子的颜色,两个相同的字母可以配对,问号可以和任何的靴子合法配对,问两个字符串最大能匹配多少对靴子,输出每对靴子的下标。

做法:直接set维护a和b的下标,然后遍历n一一配对,就可以了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+10;
int n,m;
char a[N],b[N],c[N];
set<int>ss1[200],ss2[200];
pair<int,int> ans[N];
vector<int>v;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    memset(c,0,sizeof(c));
    cin>>n;
    cin>>a>>b;
    int cnt=0;
    for(int i=0;i<n;i++)
    {
        ss1[a[i]].insert(i);
        ss2[b[i]].insert(i);
    }
    for(int i=0;i<n;i++)
    {
        int tmp=a[i];
        if(tmp!='?')
        {
            if(ss2[tmp].size()==0&&ss2['?'].size()!=0)
            {
                ans[cnt].first=i;
                ans[cnt++].second=*ss2['?'].begin();
                c[*ss2['?'].begin()]=1;
                ss2['?'].erase(ss2['?'].begin());
            }
            else if(ss2[tmp].size()!=0)
            {
                ans[cnt].first=i;
                ans[cnt++].second=*ss2[tmp].begin();
                c[*ss2[tmp].begin()]=1;
                ss2[tmp].erase(ss2[tmp].begin());
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        if(!c[i])
            v.push_back(i);
    }
    set<int>::iterator it=ss1['?'].begin();
    int i=0;
    for(;it!=ss1['?'].end()&&i<v.size();++it)
    {
        ans[cnt].first=*it;
        ans[cnt++].second=v[i++];
    }
    cout<<cnt<<endl;
    for(int i=0;i<cnt;i++)
        cout<<ans[i].first+1<<" "<<ans[i].second+1<<endl;
    return 0;
}

E. Superhero Battle

题意:给出一个生命值h和n,n表示一个周期的行动,负号表示损失生命,正号表示恢复,问这样几次行动生命值为0;

做法:先算第一个周期,能不能在不回复的情况下杀死,然后直接算出来一个周期损失的生命值,大于等于0肯定不行了,

然后再用生命值除以损失的生命值,注意提前一两个周期在处理。

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
ll h, n, a[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll sum = 0, ans = 0;
	cin >> h >> n;
	ll tmp = 0, maxn = 0;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		sum += a[i];
	}
	for (int i = 1; i <= n; i++)
	{
		if (tmp>0)
			tmp = 0;
		tmp += a[i];
		maxn = min(tmp, maxn);
	}
	tmp = h;
	ans = 0;
	for (int i = 1; i <= n; i++)
	{
		tmp += a[i];
		if (tmp <= 0)
		{
			cout << i << endl;
			return 0;
		}
	}
	if (sum >= 0)
	{
		cout << "-1" << endl;
		return 0;
	}
	ll tt = (h + maxn) / (-1*sum);
	ans += tt*n;
	h = h + tt*sum;
	int i = 1;
	while (h>0)
	{
		h += a[i];
		ans++;
		i++;
		if (i>n)
			i = 1;
	}
	cout << ans << endl;
	return 0;
}

F1,F2. Same Sum Blocks

题意:给出n个数,有k个子数组不相交且区间和相同,求k的最大值

做法:我是用map直接标记一个区间和所对应的子数组。

然后暴力枚举区间和居然过了。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int a[N],sum[N];
int n;
vector<pair<int,int> >vv;
map<int,vector<pair<int,int> > >mp;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int sum=0;
        for(int j=i;j>=1;j--)
        {
            sum+=a[j];
            if(mp[sum].size()==0||mp[sum].back().second<j)
                mp[sum].push_back(make_pair(j,i));
            if(i==1)
                ans=sum;
            if(mp[sum].size()>mp[ans].size())
                ans=sum;
        }
    }
    cout<<mp[ans].size()<<endl;
    for(auto i:mp[ans])
        cout<<i.first<<" "<<i.second<<endl;
    return 0;
}

G. Privatization of Roads in Treeland

题意:给出一个n结点的图,然后进行边的染色,如果说一个结点相连的至少两条边是相同的颜色,那么这个结点成为不好的点,问在不好的点最多为k的情况下,最少用多少种颜色去染色,并输出染色。

做法:如果有k个不好的点,则度数第k+1大的点相连的边颜色不同,答案就是度数第k+1大的度数,然后随便用dfs跑就可以了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int c[N],in[N];
int n,k,ans;
struct node
{
    int u,v;
    node(int u,int v):u(u),v(v){};
};
vector<node>g[N];
void dfs(int u,int fa,int k)
{
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].v;
        if(v==fa)
            continue;
        if(k>ans)
            k-=ans;
        c[g[u][i].u]=k++;
        dfs(v,u,k);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>k;
    int u,v;
    for(int i=1;i<=n-1;i++)
    {
        cin>>u>>v;
        in[u]++,in[v]++;
        g[u].push_back(node(i,v));
        g[v].push_back(node(i,u));
    }
    sort(in+1,in+n+1,greater<int>());
    ans=in[k+1];
    dfs(1,0,1);
    cout<<ans<<endl;
    for(int i=1;i<n;i++)
        cout<<c[i]<<" ";
    cout<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值