kickstart 2020 Round A

好没意思(((
建议kickstart更名为div4,当然我只是建议
第一次打,以后不会再打了
A:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 3e5+5;
int t,n,a[100005],b,cas;
int main(){
    ios::sync_with_stdio(false);
    cin>>t;
    while (t--){
        cas++;
        cin>>n>>b;
        for(int i=1;i<=n;i++)cin>>a[i];
        sort(a+1,a+1+n);
        int now=0;
        while (now<n&&b>=a[now+1]){
            b-=a[now+1];
            now++;
        }
        cout<<"Case #"<<cas<<": ";
        cout<<now<<endl;
    }
}

B:
dp[i][j]表示前i堆物品最多选j个的答案,枚举下一堆选多少即可

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef double db;
const int N = 3e5+5;
int t,n,k,p;
int v[55][55];
int dp[55][1555],f[55][55];
int main(){
    ios::sync_with_stdio(false);
    cin>>t;
    int cas=0;
    while (t--){
        cas++;
        memset(dp,0, sizeof(dp));
        cin>>n>>k>>p;
        for(int i=1;i<=n;i++)for(int j=1;j<=k;j++)cin>>v[i][j],f[i][j]=v[i][j]+f[i][j-1];
        for(int i=1;i<=n;i++){
            for(int j=p;j>=0;j--){
                for(int s=0;s<=j&&s<=k;s++){
                    dp[i][j]=max(dp[i][j],dp[i-1][j-s]+f[i][s]);
                }
            }
        }
        cout<<"Case #"<<cas<<": ";
        cout<<dp[n][p]<<endl;
    }
}

C:
二分

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef double db;
const int N = 1e5+5;
int t,n,k,a[N];
bool can(int x){
    int ned = 0;
    for(int i=2;i<=n;i++){
        int dis = a[i]-a[i-1];
        int c = dis/x;
        if(dis%x==0)c--;
        ned+=c;
    }
    return ned<=k;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>t;
    int cas = 0;
    while (t--){
        cas++;
        cin>>n>>k;
        for(int i=1;i<=n;i++)cin>>a[i];
        int l=1,r=1e9;
        while (l<=r){
            int mid = l+r>>1;
            if(can(mid)){
                r=mid-1;
            }else{
                l=mid+1;
            }
        }
        cout<<"Case #"<<cas<<": ";
        cout<<l<<endl;
    }
}

D:
想了几分钟,首先想到是否可以贪心选,就是每次都找一堆公共前缀最长的串拿出来
很容易发现这个贪心是对的
然后就是傻逼trie树了,时间复杂度也很好求
顺便这评测姬真强大,我memset竟然都没事。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
int t,n,k;
string s[N];
int tree[5000000][26],pre[5000000],tot;
int sum[5000000];
int cas = 0;
void insert(string str){
    int root = 0;
    for(int i=0;i<str.length();i++){
        int id = str[i]-'A';
        if(!tree[root][id])
            tree[root][id]=++tot;
        sum[tree[root][id]]++;
        pre[tree[root][id]]=root;
        root = tree[root][id];
    }
}
void slove(){
    cas++;
    int ans = 0;
    for(int i=tot;i>=1;i--){
        while (sum[i]>=k){
            int dep=0;
            int now = i;
            while (now!=0){
                sum[now]-=k;
                dep++;
                now=pre[now];
            }
            ans+=dep;
        }
    }
    cout<<"Case #"<<cas<<": ";
    cout<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>t;
    while (t--){
        cin>>n>>k;// n/k
        for(int i=1;i<=n;i++)cin>>s[i],insert(s[i]);
        slove();
        memset(pre,0, sizeof(pre));
        memset(sum,0, sizeof(sum));
//        for(int i=0;i<=tot;i++)pre[tot]=sum[tot]=0;
        tot=0;
        memset(tree,0, sizeof(tree));
    }
}

猜你喜欢

转载自www.cnblogs.com/MXang/p/12548630.html