LeetCode - 第36场双周赛

国庆放假,赛后补题.

A. 设计停车系统

简单模拟.

class ParkingSystem {
public:
    int b,m,s;

    ParkingSystem(int big, int medium, int small) {
        b=big;
        m=medium;
        s=small;
    }

    bool addCar(int carType) {
        if(carType==1){
            if(b){ --b;return true; }
            return false;
        }
        else if(carType==2){
            if(m){ --m;return true; }
            return false;
        }
        else{
            if(s){ --s;return true; }
            return false;
        }
    }
};

B. 警告一小时内使用相同员工卡大于等于三次的人

简单模拟.

class Solution {
public:
    int getM(string str){
        int h=(str[0]-'0')*10+(str[1]-'0');
        int m=(str[3]-'0')*10+(str[4]-'0');
        return h*60+m;
    }

    unordered_map<string,vector<int>> mp;

    vector<string> alertNames(vector<string>& keyName, vector<string>& keyTime) {
        int n=keyName.size();
        for(int i=0;i<n;++i){
            mp[keyName[i]].emplace_back(getM(keyTime[i]));
        }
        vector<string> ans;
        for(auto it=mp.begin();it!=mp.end();++it){
            string key=it->first;
            sort(mp[key].begin(),mp[key].end());
            bool flag=false;
            for(int i=0;i+2<(int)mp[key].size();++i){
                if(mp[key][i]+60>=mp[key][i+2]){
                    flag=true;
                    break;
                }
            }
            if(flag) ans.emplace_back(key);
        }
        sort(ans.begin(),ans.end());
        return ans;
    }
};

C. 给定行和列的和求可行矩阵

构造,题目明确一定存在可行解,因此从上往下从左往右依次在矩阵中填入数值,每次尽可能填入尽量大的值,也就是行约束和列约束的较小值,同时更新行列约束.

class Solution {
public:
    vector<vector<int>> restoreMatrix(vector<int>& rowSum, vector<int>& colSum) {
        int n=rowSum.size();
        int m=colSum.size();
        vector<vector<int>> g=vector<vector<int>>(n,vector<int>(m,0));
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                int Min=min(rowSum[i],colSum[j]);
                g[i][j]=Min;
                rowSum[i]-=Min;
                colSum[j]-=Min;
            }
        }
        return g;
    }
};

D. 找到处理最多请求的服务器

线段树.

使用一个长度为 k 的线段树维护每台服务器的空闲起始时间,线段树维护区间最小值,也就是空闲起始时间的最小值. 从前向后遍历每个待处理的任务,对于某个任务 i

  1. 若所有服务器的空闲起始时间都大于 arrival[i],则任务 i 被丢弃.
  2. 否则,查询 k%i 之后的第一台满足空闲起始时间最小值小于等于 arrival[i] 的服务器,如果找不到,再从 0 开始找( 因为 k 台服务器构成一个环).

对于 1,直接查看线段树根结点的值即可;对于 2,需要单独编写一个查询函数,递归寻找满足要求的下标.

#define node tree[id]
#define lson tree[id<<1]
#define rson tree[id<<1|1]

namespace SegTree{
    const int maxn=1e5+50;
    struct Tree{
        int le,ri,Min;
    }tree[maxn<<2];

    void build(int id,int le,int ri){
        node.le=le;
        node.ri=ri;
        node.Min=0;
        if(le==ri) return;
        int mid=le+ri>>1;
        build(id<<1,le,mid);
        build(id<<1|1,mid+1,ri);
    }

    void update(int id,int pos,int val){
        if(node.le==node.ri){
            node.Min=val;
            return;
        }
        int mid=node.le+node.ri>>1;
        if(pos<=mid) update(id<<1,pos,val);
        else update(id<<1|1,pos,val);
        node.Min=min(lson.Min,rson.Min);
    }
	
    //查询下标大于等于pos,且值小于等于val的第一处下标
    int query(int id,int pos,int val){
        if(node.Min>val) return -1;//不存在则返回-1
        if(node.le==node.ri) return node.le;
        int mid=node.le+node.ri>>1;
        if(pos>mid) return query(id<<1|1,pos,val);//pos在右子树上,直接递归右子树
        int resl=query(id<<1,pos,val);//先递归左子树,如果符合要求则返回结果
        if(resl!=-1) return resl;
        return query(id<<1|1,pos,val);//否则继续递归右子树
    }
}

class Solution {
public:
    vector<int> busiestServers(int k, vector<int>& arrival, vector<int>& load) {
        SegTree::build(1,0,k-1);
        int n=arrival.size(),cnt_max=0;
        vector<int> cnt(k,0),ans;
        for(int i=0;i<n;++i){
            if(SegTree::tree[1].Min>arrival[i]) continue;
            int pos=SegTree::query(1,i%k,arrival[i]);
            if(pos==-1) pos=SegTree::query(1,0,arrival[i]);
            cnt[pos]+=1;
            cnt_max=max(cnt_max,cnt[pos]);
            SegTree::update(1,pos,arrival[i]+load[i]);
        }
        for(int i=0;i<k;++i) if(cnt[i]==cnt_max) ans.emplace_back(i);
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值