Educational Codeforces Round 109 (Rated for Div. 2)Codeforces-1525ABCD
Posted JophieQu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 109 (Rated for Div. 2)Codeforces-1525ABCD相关的知识,希望对你有一定的参考价值。
A. Potion-making
e e + w = k 100 , ( k ∈ N ) ⟹ k 100 − k = e w \\quad {e \\over e+w} = {k \\over 100} ,(k\\in N)\\implies {k \\over 100-k} = {e \\over w} e+we=100k,(k∈N)⟹100−kk=we,显然当k和(100-k)约到最简的时候总和是最小的
void solves(){
int n;cin>>n;
if(n==100){
cout<<1<<endl;return ;
} else{
int m=100-n;
int a=n/__gcd(n,m);
int b=m/__gcd(n,m);
cout<<a+b<<endl;
}
}
B. Permutation Sort
一开始忘记考虑a[1]=n,a[n]=1的情况wa了一发
void solves(){
int n;cin>>n;
int f=0;
for(int i=1;i<=n;++i){
cin>>a[i];
if(a[i]!=i)f=1;
}
if(!f){
cout<<0<<endl;return ;
}
if(a[1]==n && a[n]==1){
cout<<3<<endl;return ;
}
if(a[1]!=1&&a[n]!=n){
cout<<2<<endl;
} else cout<<1<<endl;
}
C. Robot Collisions
显然奇数坐标和偶数坐标要分开模拟
从左到右遍历所有的人。如果第二个机器人向左走,那么它必与第一个机器人相撞相消。如果第二个机器人向右走,那么我们标记它。
如果第三个机器人向左走。如果它的左边还有被标记(没被相消)的机器人,那么第三个机器人将会与被标记的最右边的机器人相撞。如果第三个机器人向右走,我们继续标记它…剩下的机器人以此类推。
显然我们可以利用后进先出的原则分别对奇偶坐标开一个栈来维护被标记的机器人。
如果最后还有未相消的、被标记的机器人,即栈不为空,那么相邻机器人之间的字母只可能是 R R或者R L。显然如果栈的长度是奇数,则栈尾的机器人不能消掉。我们再从右端(栈顶)遍历相消。
#define endl '\\n'
const int N=3e5+7;
struct peo{
int num,idx;char dir;
}a[N];
bool cmp(peo a,peo b){
return a.num<b.num;
}
void solves(){
int n,m;cin>>n>>m;
vector<peo>a(n);
for(int i=0;i<n;++i){
cin>>a[i].num;
a[i].idx=i;
}
for(int i=0;i<n;++i) cin>>a[i].dir;
sort(a.begin(),a.end(),cmp);
vector<int>ans(n+7,-1);
vector<vector<int>>st(2);
for(int i=0;i<n;++i){
int f=a[i].num&1;
if(st[f].size()){
if(a[i].dir=='R'){ // X R
st[f].push_back(i);continue;
}
int po=st[f].back();
st[f].pop_back();
char d=a[po].dir;
if(d=='L'){ //L L
int cc=(a[i].num+a[po].num)>>1;
ans[a[i].idx]=ans[a[po].idx]=cc;
} else ans[a[i].idx]=ans[a[po].idx]=abs(a[i].num-a[po].num)>>1; //R L
} else{
st[f].push_back(i);
}
}
while(st[0].size()>1){
int i=st[0].back();
st[0].pop_back();
int j=st[0].back();
st[0].pop_back();
if(a[i].dir==a[j].dir){ // R R
ans[a[i].idx]=ans[a[j].idx]=(2*m-(a[i].num+a[j].num))>>1;
} else{ //L R
ans[a[i].idx]=ans[a[j].idx]=(2*m-abs(a[i].num-a[j].num))>>1;
}
}
while(st[1].size()>1){
int i=st[1].back();
st[1].pop_back();
int j=st[1].back();
st[1].pop_back();
if(a[i].dir==a[j].dir){ // R R
ans[a[i].idx]=ans[a[j].idx]=(2*m-(a[i].num+a[j].num))>>1;
} else{ //L R
ans[a[i].idx]=ans[a[j].idx]=(2*m-abs(a[i].num-a[j].num))>>1;
}
}
for(int i=0;i<n;++i){
cout<<ans[i]<<" ";
}cout<<endl;
}
D. Armchairs
计算前i个1移动到前j个0的最小花费。
取 第i个1移动到第j个0 和 第i个1不移动到第j个0 的最小距离。
状态转移方程
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
−
1
]
,
d
p
[
i
−
1
]
[
j
−
1
]
+
a
b
s
(
b
[
j
−
1
]
−
a
[
i
−
1
]
)
)
dp[i][j]=min(dp[i][j-1],dp[i-1][j-1]+abs(b[j-1]-a[i-1]))
dp[i][j]=min(dp[i][j−1],dp[i−1][j−1]+abs(b[j−1]−a[i−1]))
void solves(){
int n;cin>>n;
vector<int>a,b;
for(int i=1;i<=n;++i){
int x;cin>>x;
if(x)a.push_back(i);
else b.push_back(i);
}
for(int i=0;i<=a.size();++i){
for(int j=0;j<=b.size();++j) dp[i][j]=0x3f3f3f3f;
}
for(int j=0;j<=b.size();++j) dp[0][j]=0;
for(int i=1;i<=a.size();++i){
for(int j=1;j<=b.size();++j){
dp[i][j]=min(dp[i][j-1],dp[i-1][j-1]+abs(b[j-1]-a[i-1]));
}
}
cout<<dp[a.size()][b.size()]<<endl;
}
以上是关于Educational Codeforces Round 109 (Rated for Div. 2)Codeforces-1525ABCD的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33