Codeforces Round 860 (Div. 2)

A-Showstopper

#include <iostream>
#include <vector> 

using namespace std;
const int maxN=200;
int a[maxN],b[maxN],c[maxN],n;

void solve(){
	cin >> n;
	for(int i=1;i<=n;++i) cin >> a[i];
	for(int i=1;i<=n;++i) cin >> b[i];
	int maxx1=0,maxx2=0;
	for(int i=1;i<n;++i){
		maxx1=max(maxx1,max(a[i],b[i]));
		maxx2=max(maxx2,min(a[i],b[i]));
	}
	if(maxx1<=max(a[n],b[n])&&maxx2<=min(a[n],b[n])){
		cout << "YES" << endl;
	}
	else cout << "NO" << endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0); 
	int t;
	cin >> t;
	while(t--){
		solve();
	} 
	
	
	return 0;
} 

B-Three Sevens

倒序处理,在每一天没有中过奖的人中随机一个作为当前的获胜者,其余的标记为已经中过就行了

#include <iostream>
#include <vector> 
#include <map>
#include <algorithm>

using namespace std;
const int maxN=5*1e4+10;
int n,m;
vector<int> a[maxN],b;
int ts[maxN],idx=0;
map<int,int> id,last;

void solve(){
	cin >> m;
	map<int,int> vis;
	for(int i=1;i<=m;++i){
		int n;
		cin >> n;
		for(int j=1;j<=n;++j){
			int x;
			cin >> x;
			a[i].push_back(x);
		}
	}
	vector<int> ans;
	for(int i=m;i>=1;--i){
		int flag=1;
		for(int x:a[i]){
			if(vis[x]==0&&flag){
				vis[x]=1;
				ans.push_back(x);
				flag=0;
			}
			vis[x]=1;
		}
		if(flag){
			cout << "-1" << endl;
			for(int i=1;i<=m;++i) a[i].clear();
			return ;
		}
	}
	for(int i=m-1;i>=0;--i){
		cout << ans[i] << " ";
	}cout << endl;
	for(int i=1;i<=m;++i) a[i].clear();
	
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0); 
	int t;
	cin >> t;
	while(t--){
		solve();
	} 
	
	
	return 0;
} 

C-Candy Store

我们不难发现,有一个基本的贪心策略,若我们有一个打好的包,我们要尽可能的把更多的物品放进去

同时,正难则反,我们想象一下,如果有一个打好的包,其价格为 w ,则 w 要满足什么性质

首先,$\forall b_i , , b_i \mid w $

这个条件等价于 $ lcm(b_i) \mid w $

同时,有 \(\forall a_i , \frac{w}{b_i}\mid a_i\)

这个条件也可以等价于 $w \mid gcd(a_i*b_i) $

两个条件综合一下,就是看 \(lcm(b_i)\) 是否整除 \(gcd(a_i*b_i)\),如果是,则一定可以打成一包

所以我们就贪心的加入,直到不能加入为止

#include <iostream>
#include <vector> 
#include <map>
#include <algorithm>
#define int unsigned long long 

using namespace std;
const int maxN=2*1e5+10;
int n,m;
int a[maxN],b[maxN];

inline int gcd(int a,int b){
	if(b==0) return a;
	return gcd(b,a%b);
}

void solve(){
	cin >> n;
	for(int i=1;i<=n;++i)cin >> a[i] >> b[i];
	int lm=b[1],gd=a[1]*b[1],ans=1;
	for(int i=2;i<=n;++i){
		int p=(lm*b[i])/gcd(lm,b[i]),q=gcd(a[i]*b[i],gd);
		if(q%p!=0ll){
			lm=b[i],gd=a[i]*b[i];
			++ans;
		}
		else lm=p,gd=q;
	}
	cout << ans << endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0); 
	int t;
	cin >> t;
	while(t--){
		solve();
	} 
	return 0;
} 

D-Shocking Arrangement

全零列明显无解

我们发现一件事情,我们可以考虑这样一种构造方法,维护当前的序列和,如果大于 0 就加入负数,反之加入正数,由于和为 0 所以我们一直有数可加

这样看起来可以把整个序列的前缀和做的更趋近于 0 ,看起来很对

我们来证明一下,区间的和相当于前缀和的极值之差,我们发现,对于一个由此构造而出的序列,其最大值一定小于等于其已经加入的最大的元素,因为如果大于零,则一定不会继续增加,如果有新的元素使其前缀和增加大于历史最大值,则最大值将被更新,最小值亦然

所谓,前缀和的极差一定满足给定的要求,我们完成了证明

#include <iostream>
#include <vector> 
#include <algorithm>

using namespace std;

void solve(){
	int n;
	cin >> n;
	vector<int> a,a1,a2;
	for(int i=1;i<=n;++i){
		int x;cin >> x;
		a.push_back(x);
		if(x>=0) a1.push_back(x);
		else a2.push_back(x);
	}
	if(a1.empty()||a2.empty()){
		cout << "NO" << endl;
		return ;
	}
	int sum=0;
	cout << "YES" << endl;
	for(int i=1;i<=n;++i){
		int k;
		if(sum<=0&&!a1.empty()){
			cout << a1.back() << " ";
			k=a1.back();
			a1.pop_back();
		}
		else {
			cout << a2.back() << " ";
			k=a2.back();
			a2.pop_back();
		}
		sum+=k;
	}
	cout << endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0); 
	int t;
	cin >> t;
	while(t--){
		solve();
	} 
	return 0;
} 
posted @ 2023-03-27 19:45  颈流推进  阅读(26)  评论(0)    收藏  举报