YL 模拟赛总结 4

Posted on 2024-03-02 21:31  _XOFqwq  阅读(3)  评论(0编辑  收藏  举报

Problem


T1

遍历字符串,拿一个桶统计即可。

T2

\(x\) 为中位数时,我们应当尽量的让整个数列的和变小,然后直接在最后一个上加即可。

为了让整个数列有序,和最小的构造的数列应当是 \(0,0,\cdot \cdot \cdot,x,x,\cdot \cdot \cdot,x\),此时的和应是 \(\lfloor \dfrac{n+1}{2} \rfloor \times x\)

因为 \(x\) 的值具有单调性,于是我们二分 \(x\) 的值,取最大值即可。时间复杂度 \(O(n \log n)\)

但是wssb,\(\lfloor \dfrac{n+1}{2} \rfloor \times x\) 显然是 \(=S\) 的,于是答案即为 \(\dfrac{S}{\lfloor \dfrac{n+1}{2} \rfloor}\),时间复杂度 \(O(n)\)

下面是考场二分代码。

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

int t,n,s;

signed main(){
    //freopen("median.in","r",stdin);
    //freopen("median.out","w",stdout);
    cin>>t;
    while(t--){
        cin>>n>>s;
        int l=-1,r=s+1;
        while(l+1<r){
            int mid=(l+r)>>1;
            if((n/2+1)*mid<=s) l=mid;
            else r=mid;
        }
        cout<<l<<'\n';
    }
    return 0;
}

T3

直接记忆化即可。

#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;

int n,m;
int a[231],b[231];

namespace sol1{
    void solve(){
        int res=a[1]&b[1];
        for(int i=2;i<=n;i++) res|=(a[i]&b[1]);
        cout<<res;
    }
}
namespace sol2{ //正解
    int res=-1e9,tmp[231]={0},mem[531][531];
    void dfs(int x,int s){
        if(mem[x][s]) return;
        mem[x][s]=1;
        if(x==n+1){
            res=max(res,s); return;
        }
        for(int i=1;i<=m;i++) dfs(x+1,s|(a[x]&b[i]));
    }
    void solve(){
        dfs(1,0);
        cout<<res;
    }
}

signed main(){
    //freopen("xor.in","r",stdin);
    //freopen("xor.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];
    if(m==1) sol1::solve();
    else sol2::solve();
    return 0;
}

T4

状态:令 \(dp_i\) 表示买前 \(i\) 个商品的最小价格。

转移:

\[dp_i=\max(dp_{i-1}+a_i,dp_{i-k}+a_i \times 2) \]

注意需要将 \(a_i\) 排序。

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

int n,nn,ans,ss,p,k;
int dp[200031];
int c[200031];

signed main(){
    //freopen("shop.in","r",stdin);
    //freopen("shop.out","w",stdout);
    cin>>n>>p>>k;
    for(int i=1;i<=n;i++) cin>>c[i];
    sort(c+1,c+n+1);
    for(int i=1;i<=n;i++){
        dp[i]=dp[i-1]+c[i];
        if(i>=k) dp[i]=min(dp[i],dp[i-k]+c[i]*2);
    }
    for(int i=n;i>=0;i--){
        if(dp[i]<=p){ cout<<i; break; }
    }
    return 0;
}