题解

我们可以根据点积的定义,垂直于原点到给定点构成的直线作一条直线,从正无穷往下平移,第一个碰到的点就是答案

像什么,上凸壳哇

可是……动态维护上凸壳?

我们可以离线,计算每个点能造成贡献的一个询问区间[l,r]表示这个点在第l个询问和第r个询问之间存在,按照每个点的横坐标大小顺序插入线段树,我们就可以类似斜率优化构造出凸包

对于所有询问,我们可以给它们按极角排序,然后遍历线段树,如果按照极角排序,那么垂直于他们的直线斜率递减,最优点也右移

实现的方法就是一边遍历线段树,一边归并排序,每一层按照极角序遍历这个凸壳就好

代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
//#define ivorysi
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define mo 974711
#define MAXN 200005
#define RG register
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct Point {
int64 x,y;
Point(){}
Point(int64 _x,int64 _y) {
x = _x;y = _y;
}
friend Point operator + (const Point &a,const Point &b) {
return Point(a.x + b.x,a.y + b.y);
}
friend Point operator - (const Point &a,const Point &b) {
return Point(a.x - b.x,a.y - b.y);
}
friend int64 operator * (const Point &a,const Point &b) {
return a.x * b.y - a.y * b.x;
}
friend int64 dot(const Point &a,const Point &b) {
return a.x * b.x + a.y * b.y;
}
friend bool operator < (const Point &a,const Point &b) {
return a.x < b.x;
}
};
struct Inode {
Point a;int l,r;
friend bool operator < (const Inode &s,const Inode &t) {
return s.a < t.a;
}
}Ins[MAXN];
struct Qnode {
Point a;int id;
}Qry[MAXN],tmp[MAXN];
vector<Point> tr[MAXN * 4];
int N,cntI,cntQ,st[MAXN * 4];
int64 ans[MAXN];
void Insert(int u,int L,int R,int l,int r,Point a) {
if(L == l && R == r) {
int s = tr[u].size() - 1;
while(s > 0) {
if((tr[u][s] - tr[u][s - 1]) * (a - tr[u][s - 1]) >= 0) {
tr[u].pop_back();
}
else break;
--s;
}
tr[u].pb(a);
return ;
}
int mid = (L + R) >> 1;
if(r <= mid) Insert(u << 1,L,mid,l,r,a);
else if(l > mid) Insert(u << 1 | 1,mid + 1,R,l,r,a);
else {
Insert(u << 1,L,mid,l,mid,a);
Insert(u << 1 | 1,mid + 1,R,mid + 1,r,a);
}
}
void Init() {
read(N);
int t,id;int64 x,y;
for(int i = 1 ; i <= N ; ++i) {
read(t);
if(t == 1) {
read(x);read(y);
Ins[++cntI] = (Inode){Point(x,y),cntQ + 1,-1};
}
else if(t == 3) {
read(x);read(y);++cntQ;
Qry[cntQ] = (Qnode){Point(x,y),cntQ};
}
else {
read(id);
Ins[id].r = cntQ;
}
}
for(int i = 1 ; i <= cntI ; ++i) {
if(Ins[i].r == -1) Ins[i].r = cntQ;
}
sort(Ins + 1,Ins + cntI + 1);
for(int i = 1 ; i <= cntI ; ++i) {
if(Ins[i].l <= Ins[i].r) {
Insert(1,1,cntQ,Ins[i].l,Ins[i].r,Ins[i].a);
}
}
}
void Solve(int u,int L,int R) {
int mid = (L + R) >> 1;
if(L != R) {
Solve(u << 1,L,mid);Solve(u << 1 | 1,mid + 1,R);
int tl = L,tr = mid + 1,p = L;
while(tl <= mid && tr <= R) {
if(Qry[tr].a * Qry[tl].a >= 0) tmp[p++] = Qry[tl++];
else tmp[p++] = Qry[tr++];
}
while(tl <= mid) tmp[p++] = Qry[tl++];
while(tr <= R) tmp[p++] = Qry[tr++];
for(int i = L ; i <= R ; ++i) Qry[i] = tmp[i];
}
int s = tr[u].size() - 1;
if(s != -1) {
for(int i = L ; i <= R ; ++i) {
while(st[u] < s) {
if(dot(tr[u][st[u]],Qry[i].a) <= dot(tr[u][st[u] + 1],Qry[i].a)) {
++st[u];
}
else break;
}
ans[Qry[i].id] = max(ans[Qry[i].id],dot(Qry[i].a,tr[u][st[u]]));
}
} }
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve(1,1,cntQ);
for(int i = 1 ; i <= cntQ ; ++i) out(ans[i]),enter;
return 0;
}

【BZOJ】4311: 向量(线段树分治板子题)的更多相关文章

  1. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  2. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  3. bzoj 4025 二分图——线段树分治+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...

  4. BZOJ 4311: 向量( 按时间分治 + 线段树 )

    离线, 然后按时间分治, 每个向量都有出现时间[l, r], 直接插入时间线段树(一个向量只会影响O(logN)数量级的线段树节点). 在线段树每个节点弄出凸壳然后二分. 时间复杂度O(Nlog^2N ...

  5. [线段树]HDU-1754板子题入门ver

    HDU-1754 线段树数组请开到四倍 众所周知数组开小会导致re tle wa等一系列问题orz 板子就是板子,数组从零开始或是从一开始都没什么问题,就是2*root+1还是2*root+2的问题. ...

  6. bzoj 4184 shallot——线段树分治+线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4184 本来想了可持久化trie,不过空间是 nlogn (出一个节点的时候把 tot 复原就 ...

  7. loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

    题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ...

  8. BZOJ 4025: 二分图 [线段树CDQ分治 并查集]

    4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...

  9. 【BZOJ2001】[HNOI2010]城市建设(CDQ分治,线段树分治)

    [BZOJ2001][HNOI2010]城市建设(CDQ分治,线段树分治) 题面 BZOJ 洛谷 题解 好神仙啊这题.原来想做一直不会做(然而YCB神仙早就切了),今天来怒写一发. 很明显这个玩意换种 ...

随机推荐

  1. Codeforces 894.D Ralph And His Tour in Binary Country

    D. Ralph And His Tour in Binary Country time limit per test 2.5 seconds memory limit per test 512 me ...

  2. C++并发编程 thread

    std::thread C++11在标准库中为多线程提供组件, 使用线程需要包含头文件 thread, 其命名空间为 std. 启动新线程 每个进程至少有一个线程: 执行main()函数的线程, 其余 ...

  3. windows环境下封装条件wait和signal

    linux 环境有提供好的pthread_cond_wait() 和 phread_signal().pthread_broadcast() windows需要自己封装,利用semophore控制线程 ...

  4. STL源码分析-bitset

    http://note.youdao.com/noteshare?id=0ea12c1fffd3866c6eddb8dc208c109d

  5. 10.Android UiAutomator Junit 断言函数的使用

    一.断言函数介绍 1.断言函数: 确定被测试的方法是否按照预期的效果正常工作 比如说: if (假设成立){ 通过测试 }else{ 报错并终止当前用例测试 } 2.断言函数用例结构: 一个完整的测试 ...

  6. array_diff使用注意

    $lost_ids = array_diff($all_ids,$old_ids); //array_diff,$old_ids不可以为null否则返回为null;array_diff起不到效果~~~

  7. org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'sessionFactory' is defined

    请检查你在web.xml中加载spring.xml文件的时候没有加载成功,看你的路径是否正确 <context-param>  <param-name>contextConfi ...

  8. js实现数组排序

    1. JavaScript的sort()方法 var array = [1,4,-8,-3,6,12,9,8]; function compare(val1,val2){ return val1-va ...

  9. HDU 6211 卡常数取模 预处理 数论

    求所有不超过1e9的 primitive Pythagorean triple中第2大的数取模$2^k$作为下标,对应a[i]数组的和. 先上WIKI:https://en.wikipedia.org ...

  10. 微信小程序导航设置

    "tabBar": { "backgroundColor": "#ffffff", "color": "#00 ...