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;
}
浙公网安备 33010602011771号