Codeforces Round 946 (Div. 3)题解

A_Phone Desktop

​ 

题解,水题一个,不过多阐述,就是说,有两种应用,一种是2x2的,另一种是1x1的,问然后有x个1x1的应用,有y个2x2的,问这些应用最少占据多少屏幕(屏幕为5x3),这题显而易见,2x2的应用一个屏幕里最多放两个,那么我们可以先去y/2先去找2x2的应用占据多少个屏幕,然后留下来7*y/2个1x1应用的空间,然后判断y是奇数还是偶数,如果是奇数屏幕+1.留下空间,再+11,最后再去与x比较,>x说明,就是前面的那些屏幕,少了,就去x-留下空间数量再除以15,并且判断余数,是否需要再去+1

#include<bits/stdc++.h>
using namespace std;
int t;
int x,y;
int cnty,cntx;//cnty统计2x2应用占据的屏幕数
int main()
{
	cin>>t;
	while(t--)
	{
		cnty=0,cntx=0;
		cin>>x>>y;
		cnty=y/2;
		int flag=0;
		int ansx=cnty*7;
		
		if(y%2!=0){
			flag=1;
		}
		
		if(flag==1)
		{
			cnty++;
			ansx+=11;
		}
		if(x<=ansx)
		{
			printf("%d\n",cnty);
		}
		else
		{
			int sum=x-ansx;
			int sum1=sum/15;
			int sum2=sum%15;
			if(sum2!=0)
			{
				sum1++;
			}
			printf("%d\n",cnty+sum1);
		}
	}
	return 0;
}

B. Symmetric Encoding

​ 

题解:依旧水题一个,唯一难度在于读题,读不懂啥也干不了,小丑的我也是反复读了五六次也是没懂 

那么现在来说思路,这题就是说给我一个字符串,找出其中所有出现过的字符,按照字典序去排序,这个就是字符串r,然后将s串,中的每一个字符在r串中找到,然后将其对称的字符变到s串里面,然后模拟一遍直接过

#include<bits/stdc++.h>
using namespace std;
 
int t;
int n;
char s[200005];
char r[26];
int vis[26];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		memset(vis, 0, sizeof(vis));
		cin>>s;
		for(int i=0;i<n;i++)
		{
			int x=s[i]-'a';
			vis[x]++;
		}
		int len=0;
		for(int i=0;i<26;i++)
		{
			if(vis[i]>0)
			{
				r[len]='a'+i;
				len++;
			}
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<len;j++)
			{
				if(r[j]==s[i])
				{
					s[i]=r[len-1-j];
					break;
				}
			}
		}
		cout<<s<<endl;
	}
	return 0;
}

D. Ingenuity-2

 题解:这题也算简单吧,一道模拟题,但是一开始粗心还是错了两次,首先就是先来对什么时候才能有存在的情况进行说明,只有N和S的差为偶数,且E和W的差也为偶数的时候才能有解,别的都不存在解,还有就是在有解的时候,需要判断,每一步都是怎么来的,那么我们以N和S这一对进行说明·,当N和S差为整数时,那么就需要将多出来的除2,然后将多出来的赋给H即可,然后就小于同理,但是在等于0

的时候需要判断,需要将每一次往返赋给一个H或者R

#include <bits/stdc++.h>
using namespace std;
int t;
int n;
string s;

void solve()
{
	cin>>n;
	int l=0,c=0;
	cin>>s;
	int f=0;
	for(int i=0;i<n;i++){
		char x=s[i];
		if(x=='N') l++,f=1;
		else if(x=='S') l--;
		else if(x=='W') c++;
		else c--;
	}
	vector<char> ans(n,'R');
	if(abs(c)%2||abs(l)%2)
	{//特判奇数
		cout<<"NO"<<endl;
		return;
	}
	else{
		if(l<0)
		{
			for(int i=0,cnt=0;i<n;i++)
			{
				if(cnt==abs(l)/2) break;
				if(s[i]=='S'){
					ans[i]='H';
					cnt++;
				}
			}
		}
		else if(l>0)
		{
			for(int i=0,cnt=0;i<n;i++){
				if(cnt==abs(l)/2) break;
				if(s[i]=='N'){
					ans[i]='H';
					cnt++;
				}
			}
		}
		else
		{
			int f1=0,f2=0;//走一步正的走一步负即可
			for(int i=0;i<n;i++){
				if(s[i]=='S'&&f1==0) ans[i]='H',f1=1;
				if(s[i]=='N'&&f2==0) ans[i]='H',f2=1;
			}
		}
		if(l==0&&c==0&&f==1){
		//这里特判一种情况,即对于NSEW这种情况,按照上述所述我们会全部赋值为a,
		//所以如果存在两个方向都为0,我们判断一下即可
		//f则是用于判断竖直等于0是不存在还是因为总和为0的情况
			int cnt=0;
			for(int i=0;i<n;i++)
			{
				if(ans[i]=='H') cnt++;
			}
			if(cnt==0||cnt==n)
			{
				cout<<"NO"<<endl;
				return;
			}
			for(int i=0;i<n;i++) 
			cout<<ans[i];
			cout<<endl;
			return;
		}
		if(c<0)
		{
			for(int i=0,cnt=0;i<n;i++)
			{
				if(cnt==abs(c)/2) break;
				if(s[i]=='E')
				{
					ans[i]='H';
					cnt++;
				}
			}	
		}
		else if(c>0)
		{
			for(int i=0,cnt=0;i<n;i++)
			{
				if(cnt==abs(c)/2) 
				break;
				if(s[i]=='W')
				{
					ans[i]='H';
					cnt++;
				}
			}
		}
		else
		{
			int f1=0,f2=0;
			for(int i=0;i<n;i++)
			{
				if(s[i]=='W'&&f1==0) ans[i]='H',f1=1;
				if(s[i]=='E'&&f2==0) ans[i]='H',f2=1;
			}
		}
	}
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		if(ans[i]=='H') cnt++;
	}
	if(cnt==0||cnt==n){
		cout<<"NO"<<endl;
		return;
	}
	for(int i=0;i<n;i++) cout<<ans[i];
	cout<<endl;

}

int main()
{
	t=1;
	cin>>t;
	while(t--)
	{
		solve();
	}
    return 0;
}

E. Money Buys Happiness

​ 

怎么说呢?经典的01背包问题的变式,难想的点,在于不是要找最小花费的最大价值,而是说,去找最大价值的最小花费 

因为题干中说了,花费ci可以大到1e8,但是其价值总共最多1e5,算上最多五十个月,也就1e6的时间复杂度吧,然后我们就先说dp数组的含义,dp[i]代表,在i的价值下,所需要的最小花费

状态转移方程:dp[j]=min(dp[j],dp[j-h[i]]+c[i]);

判断条件:dp[j-h[i]]+c[i]<=x*(i-1)

为啥会是n-1嘞,因为公司是月底发的工资,不要想着一上来白嫖一个月工资

然后就看代码吧

#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll t;
ll m,x;
ll c[100005];
ll h[100005];
ll dp[100005];//对于i的幸福,最小的花费费用为dp[i] 
ll ans;//统计每个月总的价值 
ll maxn;
signed main()
{
	cin>>t;
	while(t--)
	{
		for(int i=1;i<=100005;i++)
		{
			dp[i]=0x3f3f3f3f3f3f3f3f;//求的是最小费用,那么肯定先将其赋值最大值 
		}
		ans=0;
		dp[0]=0;
		cin>>m>>x;
		
		for(ll i=1;i<=m;i++)
		{
			cin>>c[i]>>h[i];
			ans+=h[i];
		}
		
		for(ll i=1;i<=m;i++)
		{
			for(ll j=ans+5;j>=h[i];j--)
			{
				if(dp[j-h[i]]+c[i]<=x*(i-1))
				{
					dp[j]=min(dp[j],dp[j-h[i]]+c[i]);
				}
			}
		}
		
		for(ll j=ans;j>=0;j--)
		{
			if(dp[j]<=(m-1)*x)
			{
				printf("%lld\n",j);
				break;
			}
		}
	}
	return 0;
}

G. Money Buys Less Happiness Now

 这题一看就是反悔贪心的板子呢,我们需要去构建一个反悔堆,这里的返回堆用到那个大根堆,每次都将代价放到堆里面,由于每次都是弹出堆顶元素,我们就可以每次都将代价最大的从堆中弹出,最后统计堆中有多少元素即可

ps:这题最后一题我属实没想到,可能官方放错了顺序吧,应该这题放在那个E的前面比较好

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll t;
ll m,x;
ll c[200005];

int main()
{
	cin>>t;
	while(t--)
	{
		priority_queue<int> q;
		ll sum=0;//用于要统计幸福值 
		cin>>m>>x;
		for(int i=1;i<=m;i++)
		{
			cin>>c[i];//代价 
		}
		for(int i=1;i<=m;i++)
		{
			sum-=c[i];
		    q.push(c[i]);
		    while(sum<0)
			{
				sum+=q.top();
			    q.pop();
		    }
		    sum+=x;
		}
		printf("%lld\n",q.size());
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值