BZOJ_4311_向量_CDQ分治+线段树按时间分治

Description

你要维护一个向量集合,支持以下操作:
1.插入一个向量(x,y)
2.删除插入的第i个向量
3.查询当前集合与(x,y)点积的最大值是多少。如果当前是空集输出0

Input

第一行输入一个整数n,表示操作个数
接下来n行,每行先是一个整数t表示类型,如果t=1,输入向量
(x,y);如果t=2,输入id表示删除第id个向量;否则输入(x,y),查询
与向量(x,y)点积最大值是多少。
保证一个向量只会被删除一次,不会删没有插入过的向量

Output

对于每条t=3的询问,输出一个答案

Sample Input

5
1 3 3
1 1 4
3 3 3
2 1
3 3 3

Sample Output

18
15

HINT

n<=200000 1<=x,y<=10^6

Ans=x1*x+y1*y。
y1=-x/y *x1+Ans/y。
因为y是正数,也就是说我们只需要y轴正无穷的地方能看到的点。
于是维护上凸壳即可。
但是不会删除,考虑线段树按时间分治,对log个节点上用vector插入这个点。
然后[l,r]这段的询问向上找,在线段树的结点上用vector里的点更新答案。
可以预先把插入的点按横坐标排序,这样求凸壳就是O(n)的了。
并且询问也可以向上归并,时间复杂度O(nlogn)。
 
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {
int x=0; char s=nc();
while(s<'0'||s>'9') s=nc();
while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
return x;
}
typedef long long ll;
typedef double f2;
#define ls p<<1
#define rs p<<1|1
#define N 200050
struct Point {
ll x,y;
Point() {}
Point(ll x_,ll y_) :
x(x_),y(y_) {}
};
struct A {
Point p;
int bg,ed;
bool operator < (const A &u) const {
return p.x<u.p.x;
}
}P[N];
f2 Slp(const Point &p1,const Point &p2) {
if(p1.x==p2.x) return p2.y>p1.y?1e18:-1e18;
return 1.0*(p2.y-p1.y)/(p2.x-p1.x);
}
ll f[N];
f2 qk[N];
ll qx[N],qy[N];
vector<Point>V[N<<2];
int n,m,id,t[N],tmp[N];
Point S[N];
void update(int l,int r,int x,int y,int p,Point pp) {
if(x<=l&&y>=r) {
V[p].push_back(pp); return ;
}
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,y,ls,pp);
if(y>mid) update(mid+1,r,x,y,rs,pp);
}
Point pp;
void solve(int l,int r,int p) {
int i,lim;
if(l==r) {
lim=V[p].size();
for(i=0;i<lim;i++) {
pp=V[p][i];
f[l]=max(f[l],pp.x*qx[l]+pp.y*qy[l]);
}
return ;
}
int mid=(l+r)>>1;
solve(l,mid,ls); solve(mid+1,r,rs);
int j=l,k=mid+1; i=l;
while(j<=mid&&k<=r) {
if(qk[t[j]]>=qk[t[k]]) tmp[i++]=t[j++];
else tmp[i++]=t[k++];
}
while(j<=mid) tmp[i++]=t[j++];
while(k<=r) tmp[i++]=t[k++];
for(i=l;i<=r;i++) t[i]=tmp[i];
lim=V[p].size();
if(lim==0) return ;
int top=0;
for(i=0;i<lim;i++) {
pp=V[p][i];
while(top>1&&Slp(S[top-1],S[top])<=Slp(S[top-1],pp)) top--;
S[++top]=pp;
}
j=1;
for(i=l;i<=r;i++) {
while(j<top&&Slp(S[j],S[j+1])>=qk[t[i]]) j++;
f[t[i]]=max(f[t[i]],qx[t[i]]*S[j].x+qy[t[i]]*S[j].y);
}
}
int main() {
// freopen("tt.in","r",stdin);
// freopen("tt.out","w",stdout);
n=rd();
int opt,i,x,y;
for(i=1;i<=n;i++) {
opt=rd();
if(opt==1) {
x=rd(); y=rd();
P[++id].p=Point(x,y);
P[id].bg=m+1;
}else if(opt==2) {
x=rd();
P[x].ed=m;
if(!m) P[x].ed=-1;
}else {
m++; x=rd(); y=rd();
qk[m]=(-1.0*x/y);
qx[m]=x; qy[m]=y;
}
}
sort(P+1,P+id+1);
for(i=1;i<=id;i++) {
if(P[i].bg<=m&&P[i].ed!=-1) {
P[i].ed=P[i].ed?P[i].ed:m;
update(1,m,P[i].bg,P[i].ed,1,P[i].p);
}
// printf("%d %d\n",P[i].bg,P[i].ed);
}
for(i=1;i<=m;i++) t[i]=i;
solve(1,m,1);
for(i=1;i<=m;i++) printf("%lld\n",f[i]);
}

BZOJ_4311_向量_线段树按时间分治的更多相关文章

  1. BZOJ_4025_二分图_线段树按时间分治+并查集

    BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...

  2. 【bzoj4311】向量 线段树对时间分治+STL-vector维护凸包

    题目描述 你要维护一个向量集合,支持以下操作: 1.插入一个向量(x,y) 2.删除插入的第i个向量 3.查询当前集合与(x,y)点积的最大值是多少.如果当前是空集输出0 输入 第一行输入一个整数n, ...

  3. 【CF576E】Painting Edges 线段树按时间分治+并查集

    [CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...

  4. 【BZOJ-4184 】 Shallot 线段树按时间分治 + 线性基

    4184: shallot Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 356  Solved: 180[Submit][Status][Discu ...

  5. BZOJ_4184_shallot_线段树按时间分治维护线性基

    BZOJ_4184_shallot_线段树按时间分治维护线性基 Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻 ...

  6. Bipartite Checking CodeForces - 813F (线段树按时间分治)

    大意: 动态添边, 询问是否是二分图. 算是个线段树按时间分治入门题, 并查集维护每个点到根的奇偶性即可. #include <iostream> #include <sstream ...

  7. 【BZOJ4311】向量(线段树分治,斜率优化)

    [BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...

  8. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  9. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

随机推荐

  1. [Bzoj1112][POI2008]砖块Klo(splay)

    1112: [POI2008]砖块Klo Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2353  Solved: 831[Submit][Statu ...

  2. Linux上利用NFS实现远程挂载

    两台服务器 192.168.1.1 [WEB服务器] 192.168.1.2 [录音服务器] 说明 在192.168.1.2服务器上每天有许多录音文件生成,192.168.1.1作为WEB服务器,里面 ...

  3. Python基础语法07--面向对象+正则表达式

    Python 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. 如果你以前没有接触过 ...

  4. Mac 下解决虚拟机virtualbox 4.3和windows共享问题

    mac上面安装了最新的virtualbox,有些软件还是须要windows的. 1,在设置了共享之后,仍然不能使用 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZ ...

  5. Qt:解析命令行

    Qt从5.2版開始提供了两个类QCommandLineOption和QCommandLineParser来解析应用的命令行參数. 一.命令行写法 命令行:"-abc" 在QComm ...

  6. hdu 1250 Hat&#39;s Fibonacci

    pid=1250">点击此处就可以传送hdu 1250 Problem Description A Fibonacci sequence is calculated by adding ...

  7. 第一个MapReduce程序——WordCount

    通常我们在学习一门语言的时候,写的第一个程序就是Hello World.而在学习Hadoop时,我们要写的第一个程序就是词频统计WordCount程序. 一.MapReduce简介 1.1 MapRe ...

  8. The most widely used name server software: BIND

    https://www.isc.org/downloads/bind/ The most widely used name server software: BIND BIND is open sou ...

  9. 最简单的基于FFmpeg的AVDevice样例(读取摄像头)

    =====================================================最简单的基于FFmpeg的AVDevice样例文章列表: 最简单的基于FFmpeg的AVDev ...

  10. ArcGIS教程:分水岭

    摘要 确定栅格中一组像元之上的汇流区域. 使用方法 · 各个分水岭的值将取自输入栅格中源的值或者要素倾泻点数据.假设倾泻点为栅格数据集,则使用像元值.假设倾泻点为点要素数据集,则从指定的字段中获取值. ...