Codeforces Round 935 (Div. 3)

A - Setting up Camp

思路:判断c能否填充b让b为3的倍数

查看代码

void solve() {
    int a,b,c;
    cin>>a>>b>>c;
    int ans=a+b/3;
    b%=3;
    if(b>0&&b+c<3)cout<<-1<<'\n';
    else{
        ans+=(b+c+2)/3;
        cout<<ans<<'\n';
    }
}

 

B - Fireworks

思路:同时开炮是最优的,计算在第一炮消失前a和b能发射的最大炮数

查看代码
 void solve() {
    int a,b,m;
    cin>>a>>b>>m;
    m++;
    cout<<(m+a-1)/a+(m+b-1)/b<<'\n';
}

 

C - Left and Right Houses

思路:枚举分界线,同时维护左右的01个数

查看代码
 void solve() {
    int n;
    string s;
    cin>>n>>s;
    double p=1e9;
    int r=0,ans;
    for(int i=0;i<s.size();++i){
        if(s[i]=='1')r++;
    }
 
    for(int i=0,l=0;i<=n;++i){
        if(l>=((i+1)/2)&&r>=((n-i+1)/2)){
            double t=fabs(n*1.0/2-i);
            if(!(fabs(t-p)<eps)&&t<p){
                p=t,ans=i;
            }
        }
        if(i<n)l+=(s[i]=='0'),r-=(s[i]=='1');
    }
 
    cout<<ans<<'\n';
}

 

D - Seraphim the Owl

思路:由于可以任选a,实际上就是最后要站在m内,且最后站的位置选a,后面的所有人ab取最小值

查看代码
 void solve() {
    int n, m;
    cin>>n>>m;
    vector<int>a(n+1),b(n+1),mi(n+1),r(n+5);
    for(int i=1;i<=n;++i)cin>>a[i];
    for(int i=1;i<=n;++i){
        cin>>b[i];
        mi[i]=min(a[i],b[i]);
    }
    for(int i=n;i>=1;--i)r[i]=r[i+1]+mi[i];
    int res=LLONG_MAX;
    for(int i=1;i<=m;++i){
        res=min(res,a[i]+r[i+1]);
    }
//    if(n==m)res=0;
    cout<<res<<'\n';
}

 

E - Binary Search

思路:模拟出原本数组二分x的位置,若与x原本位置不同交换即可

查看代码
 void solve() {
    int n,x,p;
    cin>>n>>x;
    vector<int>a(n+1);
    for(int i=1;i<=n;++i){
        cin>>a[i];
        if(a[i]==x)p=i;
    }
    int l=1,r=n+1;
    while(l+1<r){
        int mid=l+r>>1;
        if(a[mid]<=x)l=mid;
        else r=mid;
    }
    if(l==p)cout<<0<<'\n';
    else{
        cout<<1<<'\n';
        cout<<p<<' '<<l<<'\n';
    }
}

 

F - Kirill and Mushrooms

思路:可以枚举选的个数k,不能选的数已经确定为前k-1个,用multiset维护剩下的可选的数,选出最大的k个数。若当前需要删的数在set里,直接在set里删即可,若不在说明在已选的数里删,还需要在set再选取一个数补回去。由于选的数是递减的,每选一次的数一定是最小的,直接维护其为最小值即可

查看代码
 void solve() {
    int n;
    cin>>n;
    multiset<int>q;
    vector<int>a(n+1),b(n+1);
    for(int i=1;i<=n;++i){
        cin>>a[i];
        q.insert(a[i]);
    }
    for(int i=1;i<=n;++i){
        cin>>b[i];
    }
    int ans=*q.rbegin(),cnt=1,low=LLONG_MAX;
    q.erase(q.find(*q.rbegin()));
    for(int i=1;2*i+1<=n;++i){
        auto p=q.lower_bound(a[b[i]]);
        if(p!=q.end()){
            q.erase(p);
            low=*q.rbegin();
            q.erase(q.find(*q.rbegin()));
        }else{
            q.erase(q.find(*q.rbegin()));
            low=*q.rbegin();
            q.erase(q.find(*q.rbegin()));
        }
        if(low*(i+1)>ans){
            ans=low*(i+1),cnt=i+1;
        }
    }
    cout<<ans<<' '<<cnt<<'\n';
}

 

G - Cook and Porridge

思路:D的范围不大,直接枚举时间用优先队列模拟排队吃饭的过程。由于原先的队列已定,并且不是按k排序的,需要将再次入队的与原先队列分开存储,再次入队的是按k排序,所以直接用优先队列维护即可。注意,在重新入队时,只有当入队时间相同时才用s来判断队列里的优先级。选取一个人打饭时,需要从原先队列队首和优先队列队首二选一,怎么选呢,求出原先队列对k的后缀最大值,可以插队的条件是大于被插队位置的后缀最大k值,可以由此来判断优先队列队首是否能插到原先队列队首前面,从而选出最先打饭的人。对于正在吃饭的人,直接用优先队列维护吃完饭的时间即可。

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=4e4+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};

struct Eq{
    int k,id,s,time;
    bool operator<(const Eq&e)const{
        if(k!=e.k)return k<e.k;
        if(time!=e.time)return time>e.time;
        return s>e.s;
    }
};
struct Eh{
    int t,id;
    bool operator<(const Eh&e)const{
        return t>e.t;
    }
};
void solve() {
    int n,D;
    cin>>n>>D;
    vector<int>k(n+1),s(n+1),r(n+1);
    for(int i=1;i<=n;++i)cin>>k[i]>>s[i];
    r[n]=k[n];
    for(int i=n-1;i>0;--i)r[i]=max(r[i+1],k[i]);
    priority_queue<Eq>q;
    priority_queue<Eh>have;
    int to=1;
    for(int i=1;i<=D;++i){

        if(q.size()){
            auto f=q.top();
            if(f.k>r[to]){
                q.pop();
                have.push({i+s[f.id],f.id});
            }else{
                have.push({i+s[to],to});
                to++;
            }
        }else{
            have.push({i+s[to],to});
            to++;
        }

        if(to>n){
            cout<<i<<'\n';
            return ;
        }
        while(have.size()&&have.top().t<=i){
            auto f=have.top();
            have.pop();
            q.push({k[f.id],f.id,s[f.id],i});
        }
    }
    cout<<-1<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

 

posted @ 2024-03-22 21:57  bible_w  阅读(15)  评论(0编辑  收藏  举报