LeetCode第95场双周赛

2023.1.7LeetCode第95场双周赛

2525. 根据规则将箱子分类

思路

根据题意模拟即可

代码

class Solution {
public:
    string categorizeBox(int a, int b, int c, int m) {
        bool f1 = false, f2 = false;
        long long t = (long long)a * b * c;
        if (a >= 1e4 || b >= 1e4 || c >= 1e4 || t >= 1e9)
            f1 = true;
        if (m >= 100)
            f2 = true;
        if (f1 && f2) return "Both";
        else if (!f1 && !f2) return "Neither";
        else if (f1 && !f2) return "Bulky";
        else return "Heavy";
    }
};

2526. 找到数据流中的连续整数

思路

使用一个变量记录连续为value的个数,该数量大于等于k说明最后k为数均为value

代码

class DataStream {
public:
    int v, k, c;
    
    DataStream(int value, int _k) {
        v = value;
        k = _k;
        c = 0;
    }
    
    bool consec(int num) {
        if (num == v) c ++ ;
        else c = 0;
        return c >= k;
    }
};

/**
 * Your DataStream object will be instantiated and called as such:
 * DataStream* obj = new DataStream(value, k);
 * bool param_1 = obj->consec(num);
 */

2527. 查询数组 Xor 美丽值

思路

目的:任意i,j,k,求(nums[i] | nums[j]) & nums[k]的值
利用位运算的性质:a | b = b | aa ^ a = 0a | a = aa & a = a
i != j时,(nums[i] | nums[j]) & nums[k] = (nums[j] | nums[i]) & nums[k],两个值异或结果为0,所有i != j的值两两配对后为0消掉
因此只用考虑i = j(nums[i] | nums[i]) & nums[k] = nums[i] & nums[k],同时当i != k时,可以和(nums[k] | nums[k]) & nums[i] = nums[k] & nums[i],进行两两配对,结果为0
故只剩下i = j = k的情况,(nums[i] | nums[i]) & nums[i] = nums[i] & nums[i] = nums[i],最后答案为所有值异或结果

代码

class Solution {
public:
    int xorBeauty(vector<int>& nums) {
        int a = 0;
        for (int i : nums) a ^= i; 
        return a;
    }
};

2528. 最大化城市的最小供电站数目

思路

二分+差分
可建造的供电站数量一定,最终电量越小越容易满足,越大越不能满足,具有二分性
二分的时间复杂度为O(logn),故需要在O(n)的时间内check,每次检查能否满足时需要给一段连续区间加上一个数,后面还需继续查询,考虑差分或者树状数组算法,但树状数组时间复杂度为O(nlogn),可能会被卡常数,故使用差分来check
此题为从左到右连续查询,需要边累加边计算原数组,即查询
动态查询则只能用树状数组

代码

typedef long long ll;

class Solution {
public:
    int n;
    
    long long maxPower(vector<int>& num, int m, int k) {
        n = num.size();
        vector<ll> s(n + 1); //前缀和数组
        vector<ll> a(n); //初始状态的电量
        for (int i = 0; i < n; i ++ ) s[i + 1] = s[i] + num[i];
        for (int i = 0; i < n; i ++ ) {
            int l = max(1, i - m + 1), r = min(i + m + 1, n);
            a[i] = s[r] - s[l - 1];
        }
        vector<ll> b(n + 2); //差分数组
        for (int i = 0; i < n; i ++ ) {
            if (i) b[i + 1] = a[i] - a[i - 1];
            else b[i + 1] = a[i];
        }
        ll l = 0, r = 1e18;
        while (l < r) {
            ll mid = l + r + 1 >> 1;
            if (check(mid, b, k, m)) l = mid;
            else r = mid - 1;
        }
        return l;
    }
    
    bool check(ll x, vector<ll> b, ll k, int m) { //x为每座城市要达到的电量,b是差分数组,k是可建造的数量,m是半径
        for (int i = 1; i <= n; i ++ ) {
            b[i] += b[i - 1]; //每次累加得出当前电量
            ll cur = b[i]; //第i座城市的电量
            if (cur < x) {
                ll t = x - cur;
                if (k < t) return false; //可建造的数量不足
                k -= t;
                int l = i, r = min(n, i + m * 2);
                b[r + 1] -= t;
                b[l] += t;
            }
        }
        return true;
    }
};

附:树状数组(tle)

区间修改,单点查询

typedef long long ll;

class Solution {
public:
    int n;
    
    long long maxPower(vector<int>& num, int m, int k) {
        n = num.size();
        vector<ll> s(n + 1);
        vector<ll> a(n);
        for (int i = 0; i < n; i ++ ) s[i + 1] = s[i] + num[i];
        for (int i = 0; i < n; i ++ ) {
            int l = max(1, i - m + 1), r = min(i + m + 1, n);
            a[i] = s[r] - s[l - 1];
        }
        ll l = 0, r = 1e18;
        while (l < r) {
            ll mid = l + r + 1 >> 1;
            if (check(mid, a, k, m)) l = mid;
            else r = mid - 1;
        }
        return l;
    }
    
    vector<ll> tree;
    
    int lowbit(int x) {
        return x & -x;
    }
    
    void ins(int p, ll x) {
        for (int i = p; i <= n; i += lowbit(i))
            tree[i] += x;
    }
    
    void update(int x, int y, ll v) {
        ins(x, v), ins(y + 1, -v);
    }
    
    ll query(int x) {
        ll res = 0;
        for (int i = x; i > 0; i -= lowbit(i))
            res += tree[i];
        return res;
    }
    
    bool check(ll x, vector<ll> a, ll k, int m) {
        tree.clear(); //注意每次清空
        tree.resize(n + 1, 0);
        for (int i = 1; i <= n; i ++ ) {
            update(i, i, a[i - 1]);
        }
        for (int i = 1; i <= n; i ++ ) {
            ll cur = query(i);
            if (cur < x) {
                ll t = x - cur;
                if (k < t) return false;
                k -= t;
                int l = i, r = min(n, i + m * 2);
                update(l, r, t);
            }
        }
        return true;
    }
};

树状数组也可以解决单点修改,区间查询的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值