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. (7)C#连DB2---oledb方式

    1安装客户端 安装DbVisualizer Free 客户端软件 2编目 用 win+r  输入 db2cmd 启动命令行 要远程操作数据库,首先要进行编目,分三个步骤: 1. 在客户端建立服务器端数 ...

  2. Codeforces 848B Rooter's Song(分类+模拟)

    题目链接 Rooter's Song 题意  有n个舞者站在x轴上或y轴上,每个人有不同的出发时间.x轴上的舞者垂直x轴正方向移动,y轴上的舞者垂直y轴正方向移动. 当x轴的舞者和y轴的舞者相遇时,他 ...

  3. 利用javascript实现在圆周上匀速划动的动画效果

    先看下效果:          

  4. luogu P3865 【模板】ST表

    题目背景 这是一道ST表经典题——静态区间最大值 请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)O(1) 题目描述 给定一个长度为 NN 的数列,和 MM 次询 ...

  5. 使用fastJson把对象转字符串首字母大小写问题的解决

    例如:文档中要求传输的字段为 但是转成json字符串后却变成了: 解决方式: 在实体类的get方法上添加@JSONField(name = " ") 注解后问题解决: 输出:

  6. Effective Java P2 Item1 Consider static factory methods instead of constructors

    获得一个类的实例的传统方法是公共的构造方法,还可以提供一个公共的静态工厂方法(一个返回值为该类实例的简单静态方法), 例如Boolean(boolean 的封装类) public static Boo ...

  7. MySql常用函数积累

    --MySql查看表结构 select column_name,data_type,CHARACTER_MAXIMUM_LENGTH,column_comment from information_s ...

  8. ios Crash Log 分析汇总

    方法一: 1.xcode 有自带的symbolicatecrash,可以将.crash文件中的16进制地址转换成可读的函数地址. symbolicatecrash位于: /Applications/X ...

  9. Xcode 技巧充电篇

    作为project师,我们最重要的事情就是熟悉我们每天使用的日常工具,但不能仅限于此.仅仅要有可能,我们应该试着掌握和定制能使我们更快.更轻松地实现终于目标的工具.以下是一些小提示和技巧,都是我在 X ...

  10. C#压缩或解压(rar和zip文件)

    /// <summary> /// 解压RAR和ZIP文件(需存在Winrar.exe(只要自己电脑上可以解压或压缩文件就存在Winrar.exe)) /// </summary&g ...