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
#贪心 #数学 #最大子段和

 京公网安备 11010502036488号
京公网安备 11010502036488号