2024.11.17 Codeforces Round 988 (Div. 3)

EssnSlaryt發表於2024-11-18

Solved:7/7

Penalty:184

Rank:21

比賽連結

好水的 Div.3。。。甚至 G 是原題繃不住了()


A. Twice

題意:給一個序列,相同的兩個數可以配對消除,求最多消除的次數。

直接開桶。

#include<bits/stdc++.h>
using namespace std;

void solve(){
    int n;
    cin>>n;
    vector<int> c(n+1);
    int ans=0;
    for(int i=0,x;i<n;++i){
        cin>>x,++c[x];
        if(c[x]==2)c[x]=0,++ans;
    }
    cout<<ans<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

B. Intercepted Inputs

題意:給一個 \(n\times m\) 的矩陣,但其所有輸入(包括 \(n\)\(m\))都被打亂,要還原 \(n,m\)

列舉 \(k-2\) 的約數看是否在輸入中。

#include<bits/stdc++.h>
using namespace std;

void solve(){
    int k;
    cin>>k;
    vector<int> c(k+1);
    for(int i=0,x;i<k;++i)cin>>x,++c[x];
    int m=k-2;
    for(int i=1;i*i<=m;++i)if(!(m%i)){
        if(i!=m/i){
            if(c[i]&&c[m/i]){
                cout<<i<<' '<<m/i<<'\n';
                return;
            }
        }
        else{
            if(c[i]>=2){
                cout<<i<<' '<<i<<'\n';
                return;
            }
        }
    }
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

C. Superultra's Favorite Permutation

題意:構造一個長度為 \(n\) 的排列,使相鄰兩數之和為合數。

注意到偶數必為合數,而我們可以先排偶數再排奇數使只有一個位置相鄰奇偶性不同(另一方面,至少有一個位置相鄰奇偶性不同)。

而最小的合數為 \(9=4+5\),故 \(n\leq 4\) 均無解。對 \(n\geq 5\),前面放偶數後面放奇數再把 \(4\)\(5\) 放到一起即可。

#include<bits/stdc++.h>
using namespace std;

void solve(){
    int n;
    cin>>n;
    if(n<=4)cout<<"-1\n";
    else{
        for(int i=n/2*2;i>=6;i-=2)cout<<i<<' ';
        cout<<"2 4 5 1 3 ";
        for(int i=7;i<=n;i+=2)cout<<i<<' ';
        cout<<'\n';
    }
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

D. Sharky Surfing

題意:在數軸上從 \(0\) 跳到 \(L\),跳躍能力初始為 \(1\)。假設當前跳躍能力為 \(k\),則你可以跳至多 \(k\) 的距離。某些區間不能落地,某些位置有加速器可以增加你的跳躍能力。問至少需要撿多少個加速器(可以經過加速器但不撿)。

按加速器的位置列舉,用大根堆維護可以撿的加速器。遇到一個區間就用加速器直到 \(k\geq r-l+2\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(x) (x).begin(),(x).end()

void solve(){
    int n,m,L;
    cin>>n>>m>>L;
    vector<int> l(n),r(n);
    vector<pii> a(m);
    for(int i=0;i<n;++i)cin>>l[i]>>r[i];
    for(int i=0;i<m;++i)cin>>a[i].first>>a[i].second;
    sort(all(a));
    ++m,a.push_back({L,0});
    priority_queue<int> pq;
    int res=0;
    ll sum=1;
    for(int i=0,j=0;i<m;++i){
        while(j<n&&a[i].first>=l[j]){
            while(i<m&&a[i].first<=r[j])++i;
            while(!pq.empty()&&sum<r[j]-l[j]+2)sum+=pq.top(),pq.pop(),++res;
            if(sum<r[j]-l[j]+2){cout<<"-1\n";return;}
            ++j;
        }
        pq.push(a[i].second);
    }
    cout<<res<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

E. Kachina's Favorite Binary String

題意:互動題。你要猜一個長度為 \(n\) 字串(\(n\) 給定),每次可以詢問它的某個子串有多少個子序列為01。最多詢問 \(n\) 次。

依次詢問 \((1,2),(1,3),\dots,(1,n)\)。答案比上一次詢問多則這一位是 \(1\) 否則是 \(0\)

設第一個非 \(0\) 的位(設為 \(p\))答案是 \(k\),則前面是 \(p-k-1\)\(1\)\(k\)\(0\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(x) (x).begin(),(x).end()

int qry(int l,int r){
    cout<<"? "<<l<<' '<<r<<endl;
    int x;
    cin>>x;
    return x;
}

void solve(){
    int n;
    cin>>n;
    int pos=0,now=0,z=0;
    string ans;
    ans.resize(n);
    for(int i=2;i<=n;++i){
        int nxt=qry(1,i);
        if(nxt>now){
            ans[i-1]='1';
            if(!pos)pos=i,z=nxt;
        }
        else ans[i-1]='0';
        now=nxt;
    }
    if(!pos){cout<<"! IMPOSSIBLE"<<endl;return;}
    for(int i=1;i<=pos-z-1;++i)ans[i-1]='1';
    for(int i=pos-z;i<=pos-1;++i)ans[i-1]='0';
    cout<<"! "<<ans<<endl;
}

int main(){
    int T;
    cin>>T;
    while(T--)solve();
}

F. Ardent Flames

題意:有 \(n\) 個敵人,第 \(i\) 個敵人位置為 \(x_i\) 血量為 \(h_i\)。你可以向同一個位置 \(p\) 扔若干個炸彈,每個炸彈會對位置為 \(x\) 的敵人造成 \(\max\{0,m-|p-x|\}\) 的傷害。求消滅 \(k\) 個敵人所需最少的炸彈數。

二分答案,設扔了 \(w\) 個炸彈,則第 \(i\) 個敵人需要被每個炸彈造成 \(t_i=\lceil \frac {h_i}w\rceil\) 的傷害。那麼消滅這個敵人需要炸彈落在 \([x_i-(m-t_i),x_i+(m-t_i)]\) 之間的位置(\(t_i>m\) 則無法消滅)。

問題轉化為給 \(n\) 個區間問是否存在一個位置被覆蓋 \(\geq k\) 次。離散化+差分即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(x) (x).begin(),(x).end()

void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<int> h(n),x(n);
    for(int i=0;i<n;++i)cin>>h[i];
    for(int i=0;i<n;++i)cin>>x[i];
    auto chk=[&](int w)->bool {
        vector<int> t(n),buc;
        for(int i=0;i<n;++i){
            t[i]=(h[i]+w-1)/w;
            if(t[i]<=m){
                buc.push_back(x[i]-m+t[i]);
                buc.push_back(x[i]+m-t[i]+1);
            }
        }
        sort(all(buc));
        buc.resize(unique(all(buc))-buc.begin());
        vector<int> c(buc.size());
        for(int i=0;i<n;++i){
            if(t[i]<=m){
                int l=lower_bound(all(buc),x[i]-m+t[i])-buc.begin();
                int r=lower_bound(all(buc),x[i]+m-t[i]+1)-buc.begin();
                ++c[l],--c[r];
            }
        }
        for(int i=1;i<buc.size();++i)c[i]+=c[i-1];
        for(int i=0;i<buc.size();++i)if(c[i]>=k)return 1;
        return 0;
    };
    int l=1,r=1e9,ans=-1;
    while(l<=r){
        int mid=(l+r)>>1;
        if(chk(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

G. Natlan Exploring

原題:這場的 J

相關文章