2021春季个人赛


LCP28.采购方案

小力将 N 个零件的报价存于数组 nums。小力预算为 target,假定小力仅购买两个零件,要求购买零件的花费不超过预算,请问他有多少种采购方案。

注意:答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1

双指针

class Solution:
    def purchasePlans(self, nums: List[int], target: int) -> int:
        n = len(nums)
        nums.sort()
        l, r = 0, n-1
        res = 0
        #print(nums)
        while r>l:
            while r>l and (nums[l]+nums[r]>target):
                r -= 1
            res += r-l
            l += 1
        return res%1000000007

LCP29.乐团站位

某乐团的演出场地可视作 num * num 的二维矩阵 grid(左上角坐标为 [0,0]),每个位置站有一位成员。乐团共有 9 种乐器,乐器编号为 1~9,每位成员持有 1 个乐器。
请返回位于场地坐标 [Xpos,Ypos] 的成员所持乐器编号。

class Solution:
    def orchestraLayout(self, num: int, x: int, y: int) -> int:
        depth = min(x, y, num-x-1, num-y-1)    #位置前面的圈数
        ans = num*num - (num-2*depth)**2       #前面几圈的数
        start, end = depth, num - depth

        if x == depth:            #左边
            ans += y - start
        elif y == depth:          #上边
            ans += (end-start-1)*3 + end - x - 1
        elif x == end - 1:
            ans += (end-start-1)*2 + end - y - 1
        else:
            ans += end-start-1 + x - start

        return ans%9 + 1

#后面还是不懂

LCP30.魔塔游戏

小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1。每个房间的补血道具/怪物对于血量影响记于数组 nums,其中正数表示道具补血数值,即血量增加对应数值;负数表示怪物造成伤害值,即血量减少对应数值;0 表示房间对血量无影响。

小扣初始血量为 1,且无上限。假定小扣原计划按房间编号升序访问所有房间补血/打怪,为保证血量始终为正值,小扣需对房间访问顺序进行调整,每次仅能将一个怪物房间(负数的房间)调整至访问顺序末尾。请返回小扣最少需要调整几次,才能顺利访问所有房间。若调整顺序也无法访问完全部房间,请返回 -1

from heapq import *
class Solution:
    def magicTower(self, nums: List[int]) -> int:
        if sum(nums) < 0: return -1 
        q = []
        cur = 1
        ans = 0
        for num in nums:
            cur += num
            if num < 0:
                heappush(q, num)
            if cur <= 0:
                cur -= heappop(q)
                ans += 1
        return ans

# 用优先队列存储可以用的梯子

LCP31.变换的迷宫

TLE(35/59),练了一下DFS

class Solution:
    def escapeMaze(self, maze: List[List[str]]) -> bool:
        self.ans = False
        rows, cols, t = len(maze[0]), len(maze[0][0]), len(maze)

        @lru_cache(None)
        def dfs(x, y, tt, a, b, c):

            # 出口处理
            if x==rows-1 and y==cols-1:
                self.ans = True
                return 
            if tt == t-1:        #最后时刻
                return

            #print(tt,t)
            #方格处理
            grid = []
            for row in maze[tt+1]:
                grid.append([i for i in row])
            #print(grid)
            if c:
                grid[c[0]][c[1]] = "."
            
            #开始暴力
            for (i,j) in [(x-1,y),(x+1,y),(x,y-1),(x,y+1),(x,y)]:  #5个位置
                if 0<=i<rows and 0<=j<cols:  
                    if  grid[i][j] == ".":               #"."直接走         
                        dfs(i, j, tt+1, a, b, c)
                    else:
                        if a:                              #使用临时消除
                            dfs(i, j, tt+1, 0, b, c)
                        if b:                              #使用永久消除
                            dfs(i, j, tt+1, a, 0, (i,j))
                        

        dfs(0, 0, 0, 1, 1, None)
        return self.ans

LCP32.批量处理任务

某实验室计算机待处理任务以 [start,end,period] 格式记于二维数组 tasks,表示完成该任务的时间范围为起始时间 start 至结束时间 end 之间,需要计算机投入 period 的时长,注意:

  • period 可为不连续时间
  • 首尾时间均包含在内
    处于开机状态的计算机可同时处理任意多个任务,请返回电脑最少开机多久,可处理完所有任务。

提示:

  • 2 <= tasks.length <= 10^5
  • tasks[i].length == 3
  • 0 <= tasks[i][0] <= tasks[i][1] <= 10^9
  • 1 <= tasks[i][2] <= tasks[i][1]-tasks[i][0] + 1
class Solution:
    def processTasks(self, tasks: List[List[int]]) -> int:
        tasks.append([10**9+1, 10**9+1, 1])  #哨兵,无法与任何任务维系
        ans, heap = 0, []  #heap表可以维系在一起的任务池
        for s, e, p in sorted(tasks, key = lambda x: x[0]): #按启动时间遍历
            while heap and heap[0][0]+ans < s: #不可维系
                if heap[0][0]+ans >= heap[0][1]: 
                    heappop(heap)
                else:
                    ans+=min(heap[0][1],s)-(heap[0][0]+ans)
            heappush(heap,[e-p+1-ans, e+1])
            #print(heap)
        return ans

#要ans最小,则处于前面的任务开始时间后移

#e-p+1, 为任务最晚启动时间,
#e-p+1-ans, 应该是把前面已用的时间剃掉的,任务最晚启动时间
#e+1, 为任务最晚时间+1

#真难,不懂
#include <bits/stdc++.h>

using namespace std;

#define POW2(X) (1<<(X))
#define CKBIT(S,X) (((S)&POW2(X))!=0)
const double pi=acos(-1.0);
const double eps=1e-11;
template<class T> inline void ckmin(T &a,T b){ a=min(a,b); }
template<class T> inline void ckmax(T &a,T b){ a=max(a,b); }
template<class T> inline T sqr(T x){ return x*x; }
#define SIZE(A) ((int)A.size())
#define LENGTH(A) ((int)A.length())
#define MP(A,B) make_pair(A,B)
#define PB(X) push_back(X)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,a) for(int i=0;i<(a);++i)
#define ALL(A) A.begin(),A.end()
template<class T> int CMP(T a[],const T b[],int n) { return memcmp(a,b,n*sizeof(T)); }
template<class T> void COPY(T a[],const T b[],int n) { memcpy(a,b,n*sizeof(T)); }
template<class T> void SET(T a[],int val,int n) { memset(a,val,n*sizeof(T)); }
using uint=unsigned int;
using int64=long long;
using uint64=unsigned long long;
using ipair=pair<int,int>;
using VI=vector<int>;
using VD=vector<double>;
using VVI=vector<VI>;
using VS=vector<string>;

class Solution
{
public:
    int processTasks(vector<vector<int>>& tasks) 
    {
        /*
        tasks.clear();
        REP(i,100000)        
        {
            int a=rand();
            int b=rand();
            if (a>b) swap(a,b);
            int c=rand()%(b-a+1)+1;
            tasks.push_back({a,b,c});
        }
        */
        struct Task
        {
            int s;
            int t;
            int length;
        };
        vector<Task> a;
        for (auto t:tasks) 
        {
            Task x;
            x.s=t[0];
            x.t=t[1];
            x.length=t[2];
            a.push_back(x);
        }
        sort(ALL(a),[](const Task& a,const Task& b) {
                return a.t<b.t;
            });
        vector<ipair> segs;
        vector<int> prefix;
        segs.push_back(MP(-1,-2));
        prefix.push_back(0);
        for (Task task:a)
        {
            assert(SIZE(segs)==SIZE(prefix));
            int total=0;
            int s=task.s;
            auto it=lower_bound(ALL(segs),MP(s,-1));
            int at=std::distance(segs.begin(),it);
            total+=prefix.back()-(at==0?0:prefix[at-1]);
            for (int i=at-1;i>=0;i--)
                if (segs[i].second<s)
                    break;
                else if (segs[i].first<=s)
                {
                    total+=segs[i].second-s+1;
                    break;
                }
                else
                    total+=segs[i].second-segs[i].first+1;
            if (total>=task.length) continue;

            total=task.length-total;
            int last=task.t;
            while (1)
            {
                ipair w=segs.back();
                int d=last-w.second;
                if (d<total)
                {
                    total-=d;
                    segs.pop_back();
                    prefix.pop_back();
                    last=w.first-1;
                    continue;
                }
                segs.push_back(MP(last-total+1,task.t));
                int tt=prefix.back()+segs.back().second-segs.back().first+1;
                prefix.push_back(tt);
                break;
            }
        }
        int ret=0;
        for (auto t:segs) ret+=t.second-t.first+1;
        return ret;
    }
};

//小马智行CTO写的...

文章作者: ╯晓~
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ╯晓~ !
评论
  目录