NOIP 模拟 $18\; \rm 老司机的狂欢$
题解 \(by\;zj\varphi\)
一道很有趣的题,我用的动态开点线段树和倍增
首先对于第一问,不难想到要二分,二分时间,因为时间长一定不会比时间短能跑的人多
那么如何 check
,先将所有老司机按初始坐标排个序,之后将每个老司机跑的距离加上,那么就是对之后的序列求一个 \(\rm LIS\)
求这个长度可以用树装数组维护值域,而求这个字典序最小的序列就需要用到倍增;类似于树上倍增,对于 \(i,j\) 的序列,他们在相同的一位之前一定是一样的,而之后哪个的最小值小,那个就更优
我们对于序列长度开一棵动态开点线段树,每个节点存的是这一段位置的最优选择,每次回溯时维护即可
复杂度就是 \(\mathcal O(\rm nlognlogt+nlog^2n)\)
Code
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
using namespace std;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
template<typename T>inline void read(T &x) {
ri f=1;x=0;register char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
x=f?x:-x;
}
}
using IO::read;
namespace nanfeng{
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
typedef long long ll;
typedef double db;
static const int N=1e5+7;
struct node{ll pos;int a,id;}dr[N];
int p[N],pi[N],pre[N][21],mn[N][21],tpr[N],dp[N],num,n,k,ed;
db pos[N],tmp[N];
priority_queue<int,vector<int>,greater<int> > quea;
inline int operator<(const node &n1,const node &n2) {return n1.pos<n2.pos;}
inline int cmp(int x,int y) {return pos[x]<pos[y];}
struct BIT{
#define lowbit(x) ((x)&-(x))
int c[N];
inline void update(int x,int len) {
for (ri i(x);i<=n;i+=lowbit(i)) c[i]=cmax(c[i],len);
}
inline int query(int x) {
int res=0;
if (!x) return res;
for (ri i(x);i;i-=lowbit(i)) res=cmax(res,c[i]);
return res;
}
}B;
struct Seg{
#define ls(x) T[x].l
#define rs(x) T[x].r
struct segmenttree{int l,r,cur;}T[N*21];
int rt[N],tot;
inline int calc(int x1,int x2) {
ri mn1=INT_MAX,mn2=INT_MAX;
ri tx1=x1,tx2=x2;
for (ri i(17);~i;--i)
if (pre[x1][i]!=pre[x2][i]) {
mn1=cmin(mn1,mn[x1][i]),mn2=cmin(mn2,mn[x2][i]);
x1=pre[x1][i],x2=pre[x2][i];
}
mn1=cmin(mn1,mn[x1][0]),mn2=cmin(mn2,mn[x2][0]);
if (mn1<mn2) return tx1;
else return tx2;
}
inline void up(int x) {
if (!ls(x)) T[x].cur=T[rs(x)].cur;
else if (!rs(x)) T[x].cur=T[ls(x)].cur;
else {
ri x1=T[ls(x)].cur,x2=T[rs(x)].cur;
T[x].cur=calc(x1,x2);
}
}
void update(int &x,int k,int p,int l,int r) {
if (!x) x=p(tot);
if (l==r) return (void)(T[x].cur=k);
int mid(l+r>>1);
if (p<=mid) update(ls(x),k,p,l,mid);
else update(rs(x),k,p,mid+1,r);
up(x);
}
int query(int x,int l,int r,int lt,int rt) {
if (!x) return 0;
if (l<=lt&&rt<=r) return T[x].cur;
int mid(lt+rt>>1),tmp1(0),tmp2(0);
if (l<=mid) tmp1=query(ls(x),l,r,lt,mid);
if (r>mid) tmp2=query(rs(x),l,r,mid+1,rt);
if (!tmp1||!tmp2) return (tmp1|tmp2);
return calc(tmp1,tmp2);
}
int tst(int x,int p,int l,int r) {
if (!x) return 0;
if (l==r) return T[x].cur;
int mid(l+r>>1);
if (p<=mid) return tst(ls(x),p,l,mid);
else return tst(rs(x),p,mid+1,r);
}
}T;
inline int check(int tim) {
num=0;
memset(B.c,0,sizeof(B.c));
memset(dp,0,sizeof(dp));
for (ri i(1);i<=n;p(i)) pos[i]=0.5*(db)dr[i].a*tim*(db)tim+(db)dr[i].pos,tmp[i]=pos[i];
sort(tmp+1,tmp+n+1);
ri kk=unique(tmp+1,tmp+n+1)-tmp;
for (ri i(1);i<=n;p(i)) pi[i]=lower_bound(tmp+1,tmp+kk,pos[i])-tmp;
for (ri i(1);i<=n;p(i)) {
ri cur=p[i],curp=pi[i];
int res=B.query(curp-1);
if (res+1>num) num=res+1;
dp[i]=res+1;
B.update(curp,res+1);
}
if (num>=k) return 1;
return 0;
}
inline int main() {
// FI=freopen("nanfeng.in","r",stdin);
// FO=freopen("nanfeng.out","w",stdout);
read(n),read(k);
for (ri i(1);i<=n;p(i)) read(dr[i].pos),read(dr[i].a),dr[i].id=i;
sort(dr+1,dr+n+1);
for (ri i(1);i<=n;p(i)) p[i]=dr[i].id;
ri l=0,r=86400,ans;
while(l<=r) {
int mid(l+r>>1);
if (check(mid)) l=mid+1,ans=mid;
else r=mid-1;
}
check(ans);
printf("%d\n",ans);
if (num>k) puts("-1");
else {
memset(mn,0x3f,sizeof(mn));
for (ri i(1);i<=n;p(i)) {
ri cur=p[i];
mn[cur][0]=cur;
if (dp[i]-1>0) {
pre[cur][0]=T.query(T.rt[dp[i]-1],1,pi[i]-1,1,n);
for (ri j(1);j<=17;p(j)) {
mn[cur][j]=cmin(mn[cur][j-1],mn[pre[cur][j-1]][j-1]);
pre[cur][j]=pre[pre[cur][j-1]][j-1];
}
}
T.update(T.rt[dp[i]],cur,pi[i],1,n);
}
ri cur=T.query(T.rt[num],1,n,1,n);
while(pre[cur][0]) quea.push(cur),cur=pre[cur][0];
quea.push(cur);
while(!quea.empty()) printf("%d\n",quea.top()),quea.pop();
}
return 0;
}
}
int main() {return nanfeng::main();}
NOIP 模拟 $18\; \rm 老司机的狂欢$的更多相关文章
- HZOJ 老司机的狂欢
比较神仙的一道题. 第一问还比较简单一点: t是否可行是单调的,考虑二分. 考虑对于两个人i,j合法的条件,设x(i)<x(j),那么$x(i)+\frac {a(i)*t^2}{2} < ...
- NOIP 模拟 $18\; \rm 炼金术士的疑惑$
题解 \(by\;zj\varphi\) 高斯消元 根据高中化学知识,求解方程的就是一直方程凑出来的,焓值也一样 那么对于要求的方程和一直方程,我们做一次高斯消元,以每个物质为未知数,因为它保证有解, ...
- NOIP 模拟 $18\; \rm 导弹袭击$
题解 \(by\;zj\varphi\) 一道凸包题 对于每个导弹,它的飞行时间就是 \(tim=\frac{A}{a_i}+\frac{B}{b_i}\) 我们设 \(x=\frac{1}{a_i} ...
- 老司机的奇怪noip模拟T2-huangyueying
2. 黄月英(huangyueying.cpp/c/pas )[问题描述]xpp 每天研究天文学研究哲学,对于人生又有一些我们完全无法理解的思考.在某天无聊学术之后, xpp 打开了 http://w ...
- 老司机谈APK瘦身套路-图片资源篇
APK作为Android系统安装包的文件格式,一直备受广大用户的关注,APK越是臃肿肥大,在下载安装过程中,它们耗费的流量会越多,安装等待时间也会越长:对于产品本身,意味着下载转化率会越低(因为竞品中 ...
- 4星|《OKR实践指南》:老司机经验谈
OKR 实践指南:知乎任向晖.雷明灿作品 (知乎「一小时」系列) 作者所在的公司已经实施了OKR十个季度了.算是目前少有的OKR老司机.书中介绍的是作者的实践经验,在目前的OKR中文书中这本算是比较少 ...
- [CSP-S模拟测试]:老司机的狂欢(LIS+LCA)
题目背景 光阴荏苒.不过,两个人还在,两支车队还在,熟悉的道路.熟悉的风景,也都还在.只是,这一次,没有了你死我活的博弈,似乎和谐了许多.然而在机房是不允许游戏的,所以班长$XZY$对游戏界面进行了降 ...
- Noip模拟18 2021.7.17 (文化课专场)
T1 导弹袭击(数学) 显然,我们要找到最优的A,B使得一组a,b优于其他组那么可以列出: $\frac{A}{a_i}+\frac{B}{b_i}<\frac{A}{a_j}+\frac{B} ...
- [BZOJ4200][Noi2015]小园丁与老司机
4200: [Noi2015]小园丁与老司机 Time Limit: 20 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 106 Solved ...
随机推荐
- Flask(10)- 标准类视图
前言 前面文章讲解 Flask 路由的时候,都是将 URL 路径和一个视图函数关联 当 Flask 框架接收到请求后,会根据请求 URL,调用响应的视图函数进行处理 Flask 不仅提供了视图函数来处 ...
- Java和C#语法对比(转)
Java C# 访问修饰符 public 修饰类.接口.变量.方法. 对所有类可见. 修饰类.接口.变量.方法. 对所有类可见. internal 无. 修饰类.接口.变量.方法. 类,接 ...
- Pandas高级教程之:window操作
目录 简介 滚动窗口 Center window Weighted window 加权窗口 扩展窗口 指数加权窗口 简介 在数据统计中,经常需要进行一些范围操作,这些范围我们可以称之为一个window ...
- Shell编程之条件语句:if、case语句
Shell编程之条件语句:if.case语句 一.条件测试 1)test命令测试 2)整数值比较 ...
- java面向对象程序设计(下)-枚举类
在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象;再比如行星类,目前只有8个对象,这些实例有限而且固定的类,在Java中被称为枚举类 JDK1.5新增了一个enum关键字,(它与 ...
- Spark RDD编程-大数据课设
目录 一.实验目的 二.实验平台 三.实验内容.要求 1.pyspark交互式编程 2.编写独立应用程序实现数据去重 3.编写独立应用程序实现求平均值问题 四.实验过程 (一)pyspark交互式编程 ...
- 【剑指offer】42.和为S的两个数字
42.和为S的两个数字 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 示例: 输入:[1,2,4,7,11 ...
- Linux虚拟机扩展磁盘
Linux虚拟机扩展磁盘 1.虚拟机关机,Vmware中扩展磁盘 2.虚拟机开机,查看磁盘大小 [root@hadoop6 ~]# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmp ...
- PAT乙级:1088 三人行 (20分)
PAT乙级:1088 三人行 (20分) 题干 子曰:"三人行,必有我师焉.择其善者而从之,其不善者而改之." 本题给定甲.乙.丙三个人的能力值关系为:甲的能力值确定是 2 位正整 ...
- 第十七篇 -- QTreeWidget与QDockWidget
效果图: 目录和工具条的创建在前面几节就已经学过了,所以目录和工具条的布局可以自己画. 那么下面的部分,左侧是一个DockWidget,里面放置一个TreeWidget.右边是一个ScrollArea ...