A. Showstopper
对于两个序列 和 ,可以进行任意次操作,每次操作可以将 进行互换.
问在进行任意次操作后,是否能够满足:
解题报告
按照题意,若 ,则让 进行交换. 随后,若 ,则让 进行交换.
在进行这些操作之后,检查序列 是否满足题意,若满足则输出 Yes
,否则输出 No
.
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n; cin>>n;
vector<int>a(n+1),b(n+1);
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i) cin>>b[i];
for(int i=1;i<n;++i)
if(a[i]>a[n]) swap(a[i],b[i]);
for(int i=1;i<n;++i)
if(b[i]>b[n]) swap(a[i],b[i]);
for(int i=1;i<n;++i)
if(a[i]>a[n] || b[i]>b[n]){
cout<<"No\n";
return;
}
cout<<"Yes\n";
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
int T; cin>>T;
while(T--) solve();
return 0;
}
时间复杂度分析
每组测试数据的时间复杂度为 .
TAG
#模拟 #暴力
B. Three Sevens
某抽奖活动将会持续 天,第 天会有 个人参与抽奖,他们的编号为 .
每天都仅有一人获奖,并且第 天获奖的人不能再参加第 天的抽奖.
现在对于给出的每天的参与抽奖的信息,问是否存在一个合法的抽奖活动的获奖名单.
解题报告
设 表示编号为 的人最后一次参与抽奖是第几天,即编号为 的人在第 天都没有再参与抽奖.
这样的人就可能是第 天的获奖的人.
检查这 天是否都有这样的人存在即可.
#include<bits/stdc++.h>
using namespace std;
const int N=50000+5;
void solve(){
int m; cin>>m;
vector<int>a_lst(N);
vector a(m,vector<int>());
for(int i=0;i<m;++i){
int n; cin>>n;
while(n--){
int x; cin>>x;
a[i].push_back(x);
a_lst[x]=i;
}
}
vector<int>ans;
for(int i=0;i<m;++i){
bool have_answer=0;
for(auto &x:a[i])
if(a_lst[x]==i){
have_answer=1;
ans.push_back(x);
break;
}
if(!have_answer){
cout<<"-1\n";
return;
}
}
for(auto &x:ans)
cout<<x<<' ';
cout<<'\n';
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
int T; cin>>T;
while(T--) solve();
return 0;
}
时间复杂度分析
每组测试数据的时间复杂度为 .
TAG
#模拟 #暴力
C. Candy Store
商店里有 种糖果,编号为 . 第 种糖果总共有 块,每块卖 元.
现在对糖果进行装袋销售,第 种糖果每袋装 块,要求 能整除 (即对于同种糖果,要求每袋糖果的块数一样). 这样每袋的售价为 .
现在将装袋好的糖果按照种类编号依次摆开,开始贴价格标签.
如果相邻的两种糖果,每袋的售价相同,则可以共用一个价格标签.
问使用最少的价格标签数量.
解题报告
考虑对于两种糖果 ,如果能够找到一个价格标签 让它们共用,则 应该满足:
如果满足 和 ,则 是肯定满足的.
即若 ,则一定有 .
即需要满足:
- 是 和 的公约数.
- 是 和 的公倍数.
进一步地说:
- 能被 整除.
- 能整除 .
- 能整除 .
故如果 能整除 ,则说明存在一个价格标签 能够让第 种糖果共用.
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
void solve(){
int n; cin>>n;
LL GCD=0,LCM=1;
int ans=1;
for(int i=1;i<=n;++i){
LL a,b; cin>>a>>b;
GCD=gcd(GCD,a*b);
LCM=lcm(LCM,b);
if(GCD%LCM){
++ans;
GCD=a*b;
LCM=b;
}
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
int T; cin>>T;
while(T--) solve();
return 0;
}
时间复杂度分析
每组测试数据的时间复杂度约为 .
TAG
#数学 #数论 #最大公约数GCD
D. Shocking Arrangement
给一个序列 ,保证 .
现在可以对序列重新排序,要求:
其中 代表 的绝对值.
问重新排序后是否能够满足要求.
解题报告
考虑如何求 .
考虑前缀和 ,有
只需要保证 ,就一定有
设当前重新排序排到了第 个位置,对于前缀和 ,有:
- 若 ,则从序列 中选择一个非负整数作为 .
- 若 ,则从序列中选择一个负数作为 .
- 可以发现,这样可以保证 ,并且由于 ,所以如上两种情况肯定都能得到满足.
但特别地,若序列 全由 组成,此时有 ,则不论怎么重新排序都不能满足 ,此时题目无解.
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n; cin>>n;
vector<int>a(n);
for(int i=0;i<n;++i) cin>>a[i];
if(*max_element(a.begin(),a.end())==0){
cout<<"No\n";
return;
}
queue<int>pos,neg;
for(int i=0;i<n;++i)
if(a[i]>=0) pos.push(a[i]);
else neg.push(a[i]);
vector<int>ans;
int sum=0;
for(int i=0;i<n;++i){
if(sum<=0){
ans.push_back(pos.front());
pos.pop();
} else {
ans.push_back(neg.front());
neg.pop();
}
sum+=ans[i];
}
cout<<"Yes\n";
for(auto &x:ans) cout<<x<<' ';
cout<<'\n';
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
int T; cin>>T;
while(T--) solve();
return 0;
}
时间复杂度分析
每组测试数据的时间复杂度为 .
TAG
#贪心 #数学 #最大子段和