Order Capital Round 1 (Codeforces Round 1038, Div. 1 + Div. 2) A - D
A. Greedy Grid
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,m;
cin>>n>>m;
if(n==1 || m==1 || (n==2 && m==2)){
cout<<"NO\n";
}
else{
cout<<"YES\n";
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
B. Pile Shuffling
因为题目保证一定有解,所有对于每一个堆,只需要考虑把多余的东西移出去即可。
如果某个堆缺少东西,则其他堆清理多余东西的时候就挪过来了
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
int ans=0;
for(int i=1;i<=n;i++){
int a,b,c,d;
cin>>a>>b>>c>>d;
ans+=max(0ll,a-c);
ans+=max(0ll,b-d);
if(b>d){
ans+=min(a,c);
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
C. Manhattan Pairs
思路在代码注释里
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
/*
答案对 X 和 Y 独立,要让答案最大,则要让 X 的答案和 Y 的答案都最大
对X:要让前n/2大的 X 和后n/2大的 X 一一结组
对Y:要让前n/2大的 Y 和后n/2大的 Y 一一结组
此时对X和对Y答案都最大
考虑有没有同时满足这两个条件的构造方式
先按照x,对点从小到到大排序,此时前一半x一定是较小的x
在分别对前一半点和后一半点,按照y从小到达排序即可
此时让(1,n), (2,n-1)....配对即为符合上述分析的解
x一定是符合的,因为是对全局排序的
y为什么也符合?前提:从小到大排序,数组左小右大
假设某次选中的两个点,y值都是前n/2,则左侧所有点都位于前n/2个
再加上选中的右侧的点,就有n/2+1个点位于前n/2
*/
struct node{
int x,y,idx;
};
void solve(){
int n;
cin>>n;
vector<node> a(n+1);
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
a[i].idx=i;
}
sort(a.begin()+1,a.end(),[&](node n1,node n2){
return n1.x<n2.x;
});
sort(a.begin()+1,a.begin()+1+n/2,[&](node n1,node n2){
return n1.y<n2.y;
});
sort(a.begin()+1,a.begin()+1+n/2,[&](node n1,node n2){
return n1.y<n2.y;
});
sort(a.begin()+1+n/2,a.end(),[&](node n1,node n2){
return n1.y<n2.y;
});
for(int i=1;i<=n/2;i++){
cout<<a[i].idx<<" "<<a[n-i+1].idx<<endl;
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
D. Traffic Lights
可以证明,存在一条路径,满足从 1 移动到 n 的时间不超过 3*n

证明来自: Max
所以只要暴力 DP t 从 1 到 3*n 的所有情况即可,一个类似与对 t 做分层图的东西
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,m;
cin>>n>>m;
vector<vector<int>> g(n+1);
while(m--){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
//可以证明,最终的时间不会很大,<=3*n
vector<int> f(n+1,inf);
f[1]=0;
int t=0;
while(1){
vector<int> tf(n+1,inf);
for(int i=1;i<=n;i++){
//当前第t秒时,在i处,枚举可以转移给谁
tf[i]=min(tf[i],f[i]+1);
int ne=g[i][(t)%g[i].size()];
tf[ne]=min(tf[ne],f[i]);
}
f=move(tf);
t++;
if(f[n]!=inf){
cout<<t<<" "<<f[n]<<endl;
return;
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}

浙公网安备 33010602011771号