【LittleXi】美团后端8.10笔试题解

第一题签到题略

第二题:

题意:

小美有一个长度为元的数组 a1,a2,...,an ,输入n,x,k他可以进行两种操作:

● 删除第一个元素 ,同时数组的长度减一,花费为 x。

● 删除整个数组,花费为 MEX(a)(其中 MEX(a)表示第一个没有出现的非负整数)

题解:

可以考虑倒序遍历,每次求出后缀的mex,然后统计答案即可

#include<vector>
#include<set>
#include<iostream>
#include<map>

// 第二题,删除数字mex
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
void solve(){
    ll n,k,x;cin>>n>>k>>x;
    vector<ll> a(n);
    for(ll&x:a) cin>>x;
    reverse(a.begin(),a.end());
    ll mex = 0;
    vector<ll> me(n+2,0);
    ll ans = n*x;
    for(ll i =0;i<n;i++){
        me[a[i]] = 1;
        while(me[mex]) mex++;
        ans = min(ans, k*mex + (n-1-i)*x);
    }
    cout<<ans<<endl;
}

signed main(){
    cin.tie(0);cout.tie(0);
    ios::sync_with_stdio(0);
    ll t;cin>>t;
    while(t--)
        solve();
}

第三题:

题意:

给一个无限长的循环五颜六色纸带,每次询问要么减去前x长度,要么减去后x长度,问每次得到的带子的颜色数量

题解:

(典中典,原题来自HH的项链https://www.luogu.com.cn/problem/P1972

可以考虑前面减和后面减情况独立

当减的长度超过n,那么全部颜色都有了,否则统计区间[l,r]颜色数量,这个可以按照r排序,每次只保留最靠近r的数字

比如1 2 1 3,枚举到0位置的时候是1 0 0 0 ,枚举到1位置的时候是 1 1 0 0 ,枚举到2位置的时候是0 1 1 0 ,枚举到3位置的时候是0 1 1 1 ,统计区间1的数量就行了

可以考虑树状数组单点修改,区间sum

#include<vector>
#include<set>
#include<iostream>
#include<map>

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

//坐标从0开始直接用的树状数组
template <typename T>
class Fenwick
{
private:
    int n;
    vector<T> c;
    int lowbits(int x){
        return (-x) & x;
    }
    int pre_sum(int i){
        int re = 0;
        for (; i > 0; i -= lowbits(i))
            re += c[i];
        return re;
    }
public:
    explicit Fenwick<T>(vector<T> v){
        this->n = v.size();
        this->c = vector<T>(n+1,0);
        for(int i=0;i<n;i++)
            add(i,v[i]);
    };
    void add(int i, int val){
        ++i;
        for (;i<=n; i += lowbits(i))
            c[i] += val;
    }
    int range_sum(int i,int j){
        ++i;++j;
        return pre_sum(j) - pre_sum(i - 1);
    }
};

vector<int> a;
vector<int> ans;

void del(vector<int> da,vector<vector<int>> qu){
    int n = da.size();
    sort(qu.begin(),qu.end(),[&](vector<int>&v1,vector<int>&v2){return v1[1] < v2[1];});
    Fenwick<int> fw(vector<int>(2*n,0));
    map<int,int> mp;
    int p = 0;
    for(int i = 0;i<qu.size();i++){
        while(p <= qu[i][1] ){
            if(mp.find(da[p])!=mp.end()){
                fw.add(mp[da[p]],-1);
            }
            fw.add(p,1);
            mp[da[p]] = p;
            p++;
        }
        ans[qu[i][2]] += fw.range_sum(qu[i][0],qu[i][1]);
    }
}

void solve(){
    int n, q , p1= 0 ,p2 = 0;
    cin>>n>>q;a = vector<int>(n);
    for(int&x:a)cin>>x;
    vector<vector<int>> ql , qr;
    ans =vector<int>(q,0);
    set<int> se(a.begin(),a.end());
    int wanz = se.size();
    for(int i = 0;i<q;i++){
        char c;cin>>c;
        int x;cin>>x;
        int wzt = x / n;
        if(wzt) ans[i] += wanz;
        if(c=='L') {
            if(x < n) ql.push_back({p1,p1+x - 1,i});
            p1 += x%n;
            if(p1>=n) p1 -= n;
        }else{
            if(x < n) qr.push_back({p2,p2+x-1,i});
            p2 += x%n;
            if(p2>=n) p2 -= n;
        }
    }
    vector<int> da = a;
    for(int x:a) da.push_back(x);
    del(da,ql);
    reverse(da.begin(),da.end());
    del(da,qr);
    for(int x:ans )cout<<x<<"\n";
}
int main(){
    cin.tie(0);cout.tie(0);
    ios::sync_with_stdio(0);
    solve();
}


♥关注LittleXi,谢谢喵,ACM金牌选手, 更新更多题解♥

全部评论
普拉那可爱捏
1 回复 分享
发布于 08-12 10:19 四川
普拉娜可爱捏
点赞 回复 分享
发布于 08-10 14:19 湖南
请问佬 这个da[p]不会越界吗,没搞懂程序哪里防止这个da[p]不越界,但所有测试样例是可以过的😂
点赞 回复 分享
发布于 08-31 18:41 北京

相关推荐

海康 嵌入式软开岗位 14k*15
点赞 评论 收藏
分享
9 15 评论
分享
牛客网
牛客企业服务