BZOJ.3938.Robot(李超线段树)
以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线。
用李超线段树维护最大最小值。对于折线分成若干条线段依次插入即可。
最好还是离线对时间离散化。
麻烦在写出来。。
复杂度\(O(c\log^2m+q\log m)\)?
以后李超树改用struct
写了...学了一种写法好方便...
//66516kb 5156ms
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#define mp std::make_pair
#define pr std::pair<int,int>
//#define gc() getchar()
#define MAXIN 500000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5,M=5e5+5;
int cnt,ref[N+M];//n+m!
char IN[MAXIN],*SS=IN,*TT=IN;
struct Line
{
int K; LL B;
LL f(int x)
{
return 1ll*K*x+B;
}
};
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define S (N+M<<2)//1~n+m!
Line mn[S],mx[S];
#undef S
void ModifyMax(int l,int r,int rt,int L,int R,Line v)
{
int m=l+r>>1;
if(v.f(ref[m])>mx[rt].f(ref[m])) std::swap(v,mx[rt]);
if(l==r) return;
if(mn[rt].f(ref[l])>=v.f(ref[l]) && mn[rt].f(ref[r])>=v.f(ref[r])) return;
// if(std::max(mn[rt].f(ref[l]),mn[rt].f(ref[r]))>=std::min(v.f(ref[l]),v.f(ref[r]))) return;//为啥上面那种写法反而慢好多啊 不应该啊= =
if(v.K<mx[rt].K) ModifyMax(lson,L,R,v);
else ModifyMax(rson,L,R,v);
}
void ModifyMin(int l,int r,int rt,int L,int R,Line v)
{
int m=l+r>>1;
if(v.f(ref[m])<mn[rt].f(ref[m])) std::swap(v,mn[rt]);
if(l==r) return;
if(mn[rt].f(ref[l])<=v.f(ref[l]) && mn[rt].f(ref[r])<=v.f(ref[r])) return;
// if(std::max(mn[rt].f(ref[l]),mn[rt].f(ref[r]))<=std::min(v.f(ref[l]),v.f(ref[r]))) return;
if(v.K>mn[rt].K) ModifyMin(lson,L,R,v);
else ModifyMin(rson,L,R,v);
}
void Modify(int l,int r,int rt,int L,int R,Line v)
{
if(L<=l && r<=R)
{
ModifyMax(l,r,rt,L,R,v), ModifyMin(l,r,rt,L,R,v);//max min分开维护.
return;
}
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,v);
if(m<R) Modify(rson,L,R,v);
}
LL Query(int l,int r,int rt,int p,int x)//x=ref[p]
{
LL val=std::max(std::abs(mx[rt].f(x)),std::abs(mn[rt].f(x)));
if(l==r) return val;
int m=l+r>>1;
return std::max(val,p<=m?Query(lson,p,x):Query(rson,p,x));
}
}T;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
inline char GetOpt()
{
register char c=gc();
while(c!='c'&&c!='q') c=gc();
return c;
}
inline int Find(int x)
{
int l=1,r=cnt,mid;
while(l<r)
if(ref[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
int main()
{
static int Q[M];
static std::vector<pr> vec[N];//每个机器人的折线 pair (time, slope)
const int n=read(),m=read();
for(int i=1; i<=n; ++i) vec[i].push_back(mp(0,read()));
int cnt=1,q=0; ref[1]=0;
for(int i=1,t,id; i<=m; ++i)
{
ref[i+1]=t=read();
if(GetOpt()=='q') Q[++q]=t;
else id=read(), vec[id].push_back(mp(t,read()));
}
ref[cnt=m+2]=1e9;
for(int tmp=cnt,i=(cnt=1,2); i<=tmp; ++i)
if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
::cnt=cnt;
for(int i=1; i<=n; ++i) vec[i].push_back(mp(1e9,0));
for(int i=1; i<=n; ++i)
{
int las=Find(vec[i][1].first);//r不需要减一啊→_→
LL pos=vec[i][0].second;
T.Modify(1,cnt,1,1,las,(Line){0,pos});
for(int j=1,lim=vec[i].size()-2,l,r,k,now; j<=lim; ++j)//lim=size(),不要写l=size() →_→
{
l=vec[i][j].first, r=vec[i][j+1].first, k=vec[i][j].second;
now=Find(r);
T.Modify(1,cnt,1,las,now,(Line){k,pos-1ll*k*l});
las=now, pos+=1ll*k*(r-l);
}
}
for(int i=1; i<=q; ++i) printf("%lld\n",T.Query(1,cnt,1,Find(Q[i]),Q[i]));
return 0;
}
BZOJ.3938.Robot(李超线段树)的更多相关文章
- BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)
BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...
- 【BZOJ 3165】 [Heoi2013]Segment 李超线段树
所谓李超线段树就是解决此题一类的问题(线段覆盖查询点最大(小)),把原本计算几何的题目变成了简单的线段树,巧妙地结合了线段树的标记永久化与标记下传,在不考虑精度误差的影响下,打法应该是这样的. #in ...
- bzoj 1568 李超线段树
博客:http://www.cnblogs.com/mangoyang/p/9979465.html 李超线段树支持两种操作:1:插入一条直线.2:询问在x = c与这些直线的交点中最大的y坐标. 插 ...
- BZOJ 3165 李超线段树
思路: 李超线段树 我是把线段转成斜率的形式搞得 不知道有没有更简单的方法 //By SiriusRen #include <cmath> #include <cstdio> ...
- 【BZOJ3165】[HEOI2013]Segment(李超线段树)
[BZOJ3165][HEOI2013]Segment(李超线段树) 题面 BZOJ 洛谷 题解 似乎还是模板题QwQ #include<iostream> #include<cst ...
- 【BZOJ1568】[JSOI2008]Blue Mary开公司(李超线段树)
[BZOJ1568][JSOI2008]Blue Mary开公司(李超线段树) 题面 BZOJ 洛谷 题解 是模板题啊. #include<iostream> #include<cs ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交
4515: [Sdoi2016]游戏 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 304 Solved: 129[Submit][Status][ ...
- 【BZOJ-3165】Segment 李超线段树(标记永久化)
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 368 Solved: 148[Submit][Sta ...
随机推荐
- 最小标示法模板 poj1509
最小标示法:给定一个字符串,不断将其最后一个字符放到开头,最终会得到n个字符串,称这n个字符串循环同构,这些字符串中字典序最小的一个,就是最小表示法 #include<iostream> ...
- Nginx详解六:Nginx基础篇之Nginx日志
1.Nginx日志类型 error.log:记录Nginx处理http请求的错误的状态,以及Nginx服务本身服务运行的错误的状态 access_log:记录通过Nginx的http请求的访问状态,用 ...
- 为什么访问json接口出现文件下载
在IE9,10,11下,当服务器端返回数据格式为json,且明确设置Content-Type为”application/json;charset=utf-8“时,会提示文件下载.如图所示: 解决办法是 ...
- centos7.4/rehat7.0系统安装
以下是安装过程:(图解),以下是rehat为例 这里可以改为centos的镜像 之后就可以用了,记得做快照!!! 拓展:分离使用 效果:
- 饮冰三年-人工智能-linux-01通过VM虚拟机安装contes系统
先决条件:VM虚拟机的安装.contes系统的镜像文件 1:创建新的虚拟机 2:下一步,稍后安装操作系统 3:选择对应的系统 4:选择对应的路径 至此虚拟机已经创建完成(相当于买了一台新电脑) 5:编 ...
- Python学生信息管理系统的开发
# 第一题:设计一个全局变量,来保存很多个学生信息:学生(学号, 姓名,年龄):思考要用怎样的结构来保存:# 第二题:在第一题基础上,完成:让用户输入一个新的学生信息(学号,姓名,年龄):你将其保存在 ...
- Android常用框架和控件使用
Router框架 https://github.com/iqiyi/Andromeda/blob/master/CHINESE_README.md https://github.com/alibaba ...
- Oozie如何和安装部署
1.Oozie的简单介绍: .Oozie是一个工作流引擎服务器,用于运行hadoop map/reduce和hive等任务工作流,同时Oozie还是一个Java web程序,运行在Java Servl ...
- HL7体系入门级介绍【转】
HL7的简单介绍1)HL7 缩写于Health Level Seven,是创建于1987年,用来发展独立卫生保健行业的电子交换交换标准,经过多年的发展,HL7已经有多个版本, 目前我们 的集 ...
- 2018 UESTC 线段树专题
A - 一棵简单的线段树 A[1...n]初始全为0. 1. 给两个数p 和 x(1≤p≤n),单点更新 A[p] <- x 2. 给两个数L和R (1≤L<R≤n), L到R区间里这几 ...