UOJ#49. 【UR #3】铀仓库

数轴上n<=500000个点,点i在Xi处有Ai个东西,Xi递增,每秒钟可移动一单位并瞬间拿或放一个东西,最多能同时拿一个东西,任选择一个点在T<=1e18秒内把尽可能多的东西拿到该点。

感谢KPM大佬提供的解法!方便快捷!

最优方案一定是在这n个点上,因此枚举点看如何计算最优答案。

越往右边的点取到的最多点数的区间不一定越往右,如图:

上图中,选择的点向右移动后,拿到右边一堆点的代价变小,从而可以拿到左边更远的点,因此排除单调性,考虑二分。

可以发现到最优情况下到左右走的最远长度是一样的,但如果二分长度还要再二分找到与长度对应的点,复杂度难以接受。

因此直接在左右两边分别二分点下标,直接统计答案,再判定完一次后,如果该次判定成功,那么更新答案后,把离枚举的点近的一边往远处二分;失败则把离枚举的点远的一边往近处二分。

这样会有两个小问题。一,存在最优方案不一定要取完某个点上的所有东西。因此判断时,看T是否落在 最远的点只取一个 到 最远的点全部取 这两个答案之间,如果是就最远的点取部分,T大了就全取,T小了就不更新答案。二,当一边停止二分时,另一边应继续二分下去,这里需要很多的判断,见代码。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 //#include<iostream>
 6 using namespace std;
 7
 8 #define LL long long
 9 int n;LL T;
10 #define maxn 500011
11 LL x[maxn],a[maxn],sumax[maxn],suma[maxn];
12 void right(int &l,int r,int mid) {l=r==mid?r:mid+1;}
13 void left(int l,int &r,int mid) {r=l==mid?l:mid-1;}
14 int main()
15 {
16     scanf("%d%lld",&n,&T);T>>=1;
17     for (int i=1;i<=n;i++) scanf("%lld",&x[i]);
18     LL ans=0;
19     for (int i=1;i<=n;i++) scanf("%lld",&a[i]),ans=max(ans,a[i]);
20     sumax[0]=suma[0]=0;
21     for (int i=1;i<=n;i++)
22     {
23         sumax[i]=sumax[i-1]+x[i]*a[i];
24         suma[i]=suma[i-1]+a[i];
25     }
26     for (int i=1;i<=n;i++)
27     {
28         int ll=1,lr=i,rl=i,rr=n;
29         while (ll<=lr && rl<=rr)
30         {
31             int lmid=(ll+lr)>>1,rmid=(rl+rr+1)>>1;
32             LL sl=x[i]-x[lmid],sr=x[rmid]-x[i];
33             LL whole=(suma[i]-suma[lmid-1])*x[i]-(sumax[i]-sumax[lmid-1])+(sumax[rmid]-sumax[i])-(suma[rmid]-suma[i])*x[i];
34             LL sing=whole-(sl<sr?sr*(a[rmid]-1):sl*(a[lmid]-1));
35             if (T<sing)
36             {
37                 if (ll==lr && rl<rr) left(rl,rr,rmid);
38                 else if (ll<lr && rl==rr) right(ll,lr,lmid);
39                 else if (ll<lr && rl<rr)
40                 {
41                     if (sl<sr) left(rl,rr,rmid);
42                     else right(ll,lr,lmid);
43                 }
44                 else break;
45             }
46             else
47             {
48                 if (max(sl,sr) && sing<=T && T<=whole)
49                 {
50                     LL tmp=(sl<sr?suma[rmid-1]-suma[lmid-1]+(T-sing)/sr+1:suma[rmid]-suma[lmid]+(T-sing)/sl+1);
51                     ans=max(ans,tmp);
52                 }
53                 else if (T>whole) ans=max(ans,suma[rmid]-suma[lmid-1]);
54                 if (ll==lr && rl<rr) right(rl,rr,rmid);
55                 else if (ll<lr && rl==rr) left(ll,lr,lmid);
56                 else if (ll<lr && rl<rr)
57                 {
58                     if (sl<sr) left(ll,lr,lmid);
59                     else right(rl,rr,rmid);
60                 }
61                 else break;
62             }
63         }
64     }
65     printf("%lld\n",ans);
66     return 0;
67 }

时间: 2024-11-03 21:04:07

UOJ#49. 【UR #3】铀仓库的相关文章

UOJ【UR #12】实验室外的攻防战

题意: 给出一个排列$A$,问是否能够经过以下若干次变换变为排列$B$ 变换:若${A_i> A_i+1}$,可以${swap(A_i,A_i+1)}$ 考虑一个数字从A排列到B排列连出来的路径与其他数字是否相交,相交就表示大小关系需要判断,(类似于二维偏序)用线段树维护区间最小值即可. 权值为1,2的线分别与权值为4的线相交,而且4在它们左边,所以需要判断它们的大小关系,发现${4>1}$,${4>2}$,所以满足条件. 1 #include<iostream> 2 #in

[UOJ #180][UR #12]实验室外的攻防战(树状数组)

Description 时针指向午夜十二点,约定的日子——2月28日终于到来了.随着一声枪响,伏特跳蚤国王率领着他的跳蚤大军们包围了 picks 博士所在的实验室. 当然,picks 博士不会坐以待毙,他早就率领着他的猴子们在实验室外修筑了许多的坚固防御工事. 经过跳蚤侦察兵的勘察,跳蚤国王发现 picks 博士的防御工事有着 n 处薄弱点,于是他把他的跳蚤大军分成了 n 支小队,并打算让它们分别进攻每一个薄弱点.但是因为战场混乱,这 n 支小队的位置被打乱了,重新整队之后,跳蚤国王发现第 i

【UOJ Round #3】

枚举/二分 C题太神窝看不懂…… 核聚变反应强度 QwQ很容易发现次小的公约数一定是gcd的一个约数,然后……我就傻逼地去每次算出a[1],a[i]的gcd,然后枚举约数……这复杂度……哦呵呵... 正解是先找到a[1]的所有质因数啊……然后在刚刚那个算法的“枚举gcd的约数”的时候直接枚举这些质因数就好了…… 1 //UOJ Round3 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #in

开坑UR

会做几道算几道吧…… 开个坑比较能激励自己 强迫症buff+拖延症buff rating神马的?不要在意嘛 没写的都是坑 ~~~~~萌萌哒分割线~~~~~ UR#1 1 缩进优化 2 外星人 3 跳蚤国王下江南 UR#2 1 猪猪侠再战括号序列 2 跳蚤公路 3 树上GCD UR#3 1 核聚变反应强度 2 铀仓库 3 链式反应 UR#4 1 元旦三侠的游戏 只需目测就可以发现,我们可以table[b][a] 然后除了b=1的很长之外,其它都是sqrt(n)以下的 所以可以记忆化,然后b=1时把

多线程中的锁的几种用法总结

一.ReentrantLock 1 package com.ietree.basicskill.mutilthread.lock; 2 3 import java.util.concurrent.locks.Lock; 4 import java.util.concurrent.locks.ReentrantLock; 5 6 /** 7 * Created by Administrator on 2017/5/17. 8 */ 9 public class UseReentrantLock {

【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)

http://uoj.ac/problem/31 纪念伟大的没有调出来的splay... 竟然那个find那里写错了!!!!!!!!!!!!! 以后要记住:一定要好好想过! (正解的话我就不写了,太简单了.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #

uoj #31. 【UR #2】猪猪侠再战括号序列 贪心

#31. [UR #2]猪猪侠再战括号序列 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/31 Description 大家好我是来自百度贴吧的_叫我猪猪侠,英文名叫_CallMeGGBond. 我不曾上过大学,但这不影响我对离散数学.复杂性分析等领域的兴趣:尤其是括号序列理论,一度令我沉浸其中,无法自拔.至于OI算法竞赛,我年轻时确有参加,虽仅获一枚铜牌,但我素性淡泊,毫不在意,毕竟那所谓FFT.仙人掌之类

uoj #118. 【UR #8】赴京赶考 水题

#118. [UR #8]赴京赶考 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/118 Description 高中,高中,短暂的三年.NOI是高中结业考试,而高考在每年暑假举行. 高二暑假,这是你最后一次参加高考的机会.你已经为了高考停课很久了,OI的知识很久没管了.你并没有能力用一年时间补起别人三年的OI课程.这是你的最后一战,如果你失败了,可能就不能工地搬砖只能去清华了. 这天你背上行囊赴京赶考.此时

[UOJ#192]【UR #14】最强跳蚤

[UOJ#192][UR #14]最强跳蚤 试题描述 在人类和跳蚤的战争初期,人们凭借着地理优势占据了上风--即使是最强壮的跳蚤,也无法一下越过那一堵坚固的城墙. 在经历了惨痛的牺牲后,跳蚤国王意识到再这样下去,跳蚤国必败无疑.然而为了震慑跳蚤国的老冤家--猴族,跳蚤国那世界上最跳的坦克只能留在跳蚤国本土,无法派上用场. 于是跳蚤国王决定利用跳蚤国最尖端的技术,创造出最强的跳蚤来挽回败局. 为了避免这样的低级失误,跳蚤国王决定使用机器来帮助他创造跳蚤.他把它拥有的 \(n\) 种属性放在了 \(