Codeforces Round 870 (Div. 2)

Problem - A - Codeforces

思路:

  1. 可以从小到大排序,设当前已经有cnt人说了真话(初始为0),如果至少a[i]人说假话是小于等于n-cnt的,我们就可以认为他说的真话。cnt++
  2. 最后判断说真话的人中最大的a[i]是不是小于n-cnt,是则是情况符合,否则,这个被归为真话的人说的是假话,矛盾
#include <bits/stdc++.h>
using namespace std;
#define ll               long long
#define endl             "\n"
const int N = 2e5 + 10;
int a[N];
void mysolve()
{
	int n;
	cin>>n;
	for(int i=1; i<=n; ++i)cin>>a[i];
	sort(a+1,a+1+n);
	int cnt=0,p=-1;
	for(int i=1; i<=n; ++i)
		{
			if(a[i]==p)cnt++;
			else
				{
					if(n-cnt>=a[i])cnt++,p=a[i];//记录真话
					else break;
				}
		}
	if(n-cnt>=p)cout<<n-cnt<<endl;
	else cout<<-1<<endl;
}

int32_t main()
{
	std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t=1;
	cin >> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

Problem - D - Codeforces

思路:

  1. 把公式拆开就是(b[1]+l +b[2] +b[3]-r),显然我们可以预处理前缀与后缀的最大值,枚举每个b[2],然后求最大值
#include <bits/stdc++.h>
using namespace std;
#define ll               long long
#define endl             "\n"
const int INF = 0x3f3f3f3f;         //int型的INF
const int N = 2e5 + 10;
int a[N],l[N],r[N];
void mysolve()
{
	int n;
	cin>>n;
	for(int i=1; i<=n; ++i)cin>>a[i],l[i]=max(l[i-1],a[i]+i);
	r[n+1]=-INF;
	for(int i=n; i>=1; --i)r[i]=max(r[i+1],a[i]-i);//预处理前后缀最大值
	int ans=-INF;
	for(int i=2; i<n; ++i)ans=max(ans,a[i]+l[i-1]+r[i+1]);
	cout<<ans<<endl;
}

int32_t main()
{
	std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t=1;
	cin >> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

Problem - E - Codeforces

思路:

  1. 如果我们知道拓扑序,那显然就是对拓扑序dp遍可获得答案了。
  2. 那么如何获得拓扑序呢,可以状态压缩,我们可以初始每个模特在每个城市都是值比别人大。
  3. 之后枚举每个城市,该模特对于其他人,比如i,只要在任意城市中有一个城市是值比模特i的值小。不符合,与上0。(否则与上1,就是没变化)。i个城市枚举后就可以获得每个人比别人大的bitset
#include <bits/stdc++.h>
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
const int N = 5e3 + 10;

void mysolve()
{
	int n,m;
	cin>>n>>m;
	vector<int>p(m);
	vector<vector<int>>a(n,vector<int>(m));
	for(int i=0; i<m; ++i)cin>>p[i];
	for(int i=0; i<n; ++i)for(int j=0; j<m; ++j)cin>>a[i][j];
	vector<bitset<N>>bs(m);
	for(int i=0; i<m; ++i)bs[i].set();//初始都是比其他人大,都为1
	for(int i=0; i<n; ++i)//枚举每个城市
		{
			vector<int>id(m);
			for(int j=0; j<m; ++j)id[j]=j;
			sort(id.begin(),id.end(),[&](int x,int y)//按照当前城市的值给每个模特排序
			{
				return a[i][x]<a[i][y];
			});
			bitset<N>tmp;//记录那些比当前j值小的模特
			for(int j=0; j<m; ++j)
				{
					int k=j;
					while(k<m-1&&a[i][id[k]]==a[i][id[k+1]])k++;
					for(int t=j; t<=k; ++t)bs[id[t]]&=tmp;//显然,在该城市中,j只比tmp中为1的模特值大,所以&tmp(这个影响是永久的)
					for(int t=j; t<=k; ++t)tmp.set(id[t]);
					j=k;
				}
		}
	vector<int>dp(m);
	vector<int>id(m);
	for(int j=0; j<m; ++j)id[j]=j;
	sort(id.begin(),id.end(),[&](int x,int y)//可以取任意城市的值来排序获得没有比别人大的点,以他为起点进行dp
	{
		return a[0][x]<a[0][y];
	});
	for(auto v:id)
		{
			dp[v]=p[v];
			for(int i=0; i<m; ++i)if(bs[v][i])//枚举比他一直比他小的模特
					{
						dp[v]=max(dp[v],dp[i]+p[v]);
					}
		}
	cout<<*max_element(dp.begin(),dp.end())<<endl;
}

int32_t main()
{
	std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t=1;
	//cin >> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值