牛客周赛 Round 56

A.面包店故事

n-x>=y

void solve(){
    int x,y,n;
    cin>>x>>y>>n;
    if(n-x>=y){
        cout<<"YES";
    }else{
        cout<<"NO";
    }
}

B.放课后的故事

注意《一起》

void solve(){
    ll n,m,k;
    cin>>n>>m>>k;
    vector<int> a(n+1);
    ll sum = 0;
    for(int i = 1;i<=n;i++) cin>>a[i],sum+=a[i];
    ll cnt = sum/k;
    cout<<min(cnt,m+1);
}

C.异或故事

注意到可以把单独的最后一位的1取出来,所以直接lowbit就行,但特例是2的n次方,因为2的n次方二进制只有一个1,所以不能lowbit,直接x+1和1就行,但n==0的话,可以参考样例给的2 3

int lowbit(int x){
    return x&(-x);
}
void solve(){
    int n;
    cin>>n;
    int res = 2;
    for(int i = 1;i<=32;i++,res*=2){
        if(res==n){
            cout<<"1"<<' '<<n+1<<endl;
            return ;
        }
    }
    if(n==1){
        cout<<"2 3"<<endl;
        return ;
    }else{
        cout<<lowbit(n)<<' '<<n-lowbit(n)<<endl;
    }
}

D.构造故事

有点原题的意思,记得牛客之前有一道删去某个可选边可以组成的三角形最大边长,可以证明,组成边长最大值的三条边一定在排序后相邻,所以暴力枚举就行

bool check(int a,int b,int c){
    if(a+b>c&&a+c>b&&b+c>a) return true;
    else return false;
}

void solve(){
    int n;
    cin>>n;
    vector<ll> a(n);
    for(auto &x : a){
        cin>>x;
    }
    sort(a.begin(),a.end());
    ll ans = 0;
    
    bool suc = false;
    for(int i = 0;i<n-2;i++){
        if(check(a[i],a[i+1],a[i+2])) ans = max(ans,a[i]+a[i+1]+a[i+2]),suc = true;
        
    }
    
    
    if(!suc){
        cout<<"-1"<<endl;
    }else{
        cout<<ans<<endl;
    }
}

E.约会故事

这题超级大暴力,有一个坑点是开心的时间可能是跨度23:xx和01:xx,所以可以考虑用24*60的数组去存happytime,原理是差分,因为发现只用到了零点到两点的时间,,再开一个set去存喜欢的饮料,利用count函数去判断喜不喜欢饮料

#include <bits/stdc++.h>
using namespace std;
const int N = 2000;
int t[N];
int main()
{
    int n,m;
    cin>>n>>m;
    
    for(int i = 1;i<=n;i++){
        int a,b,c,d;
        scanf("%d:%d %d:%d",&a,&b,&c,&d);
        if(a*60+b==c*60+d) {t[0]++;t[24*60]--;}
        else if(a*60+b<c*60+d)
        {
            t[a*60+b]++;
            t[c*60+d+1]--;
        }
        else
        {
            t[c*60+d]++;
            t[24*60]--;
            t[0]++;
            t[a*60+b+1]--;
        }
    }
    
    for(int i=1;i<=24*60-1;i++) t[i]+=t[i-1];
    
    set<string> ss;
    while(m--)
    {
        string s;
        cin>>s;
        ss.insert(s);
    }
    
    int q;
    cin>>q;
    
    while(q--){
        bool suc1 = false;
        bool suc2 = true;
        
        int invh,invs;
        scanf("%d:%d",&invh,&invs);
        int a,b,c,d;
        scanf("%d:%d %d:%d",&a,&b,&c,&d);
        string drink;
        cin>>drink;
        
        if(t[invh*60+invs]&&invh*60+invs<=119) suc1 = true;
        
        if(a*60+b>c*60+d) suc2 = false;
        
        if(ss.count(drink)==0) suc2 = false;
        
        if(!suc1){
            cout<<"Loser xqq"<<endl;
        }else{
            if(!suc2) cout<<"Joker xqq"<<endl;
            else cout<<"Winner xqq"<<endl;
        }
    }    
}

F.不是烤串故事

本题卡自然溢出法哈希

 二分+字符串哈希,直接开三个哈希数组,s和t本身的哈希,反转之后的s的哈希然后遍历每个反转位的lcp,这一步用二分,本人也很菜,也是看别人的代码

const int P = 13331;
const i64 mod = 1610612741;
void solve()
{
    int n;
    std::cin >> n;
    std::string s, t;
    std::cin >> s >> t;
    std::vector<i64> p(n + 1), hs(n + 1), rhs(n + 1), ht(n + 1);
    p[0] = 1;
    for (int i = 0; i < n; i ++) {
        p[i + 1] = p[i] * P % mod;
        hs[i + 1] = (hs[i] * P + s[i]) % mod;
        ht[i + 1] = (ht[i] * P + t[i]) % mod;
    }
    std::reverse(all(s));
    for (int i = 0; i < n; i ++) {
        rhs[i + 1] = (rhs[i] * P + s[i]) % mod;
    }
    int max = -1;
    int pos = 0;
    auto gethash = [&](std::vector<i64>& h, int l, int r) -> i64 {
        return ((h[r] - h[l - 1] * p[r - l + 1]) % mod + mod) % mod;
    };  
    auto check = [&](int id, int x) -> bool {
        u64 S;
        if (x <= id) {
            S = gethash(rhs, n - id + 1, n - id + x);
        }
        else {
            S = (gethash(rhs, n - id + 1, n) * p[x - id] % mod + gethash(hs, id + 1, x)) % mod;
        }
        u64 T = ht[x];
        // std::cerr << S << " " << T << '\n';
        return S == T;
    };
    for (int i = 1; i <= n; i ++) {
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            // std::cerr << l << " " << r << " " << mid << '\n';
            if (check(i, mid)) {
                l = mid;
            }
            else {
                r = mid - 1;
            }
        }
        // std::cerr << l << "\n\n";
        if (max < l) {
            max = l;
            pos = i;
        }
    }
    std::cout << max << ' ' << pos << '\n';
}

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值