bzoj4311向量(线段树分治+斜率优化)

第二道线段树分治。

首先设当前向量是(x,y),剩余有两个不同的向量(u1,v1)(u2,v2),假设u1>u2,则移项可得,若(u1,v1)优于(u2,v2),则-x/y>(v1-v2)/(u1-u2),然后维护上凸壳后进行三分即可,复杂度O(nlog2n),如果将询问排序扫一遍,可以优化到O(nlogn),当然我没写。

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N=2e5+7;
struct node{int x,y,l,r;}p[N],q[N];
int n,tim,tot,top;
ll ans[N];
vector<node>a[N<<2];
node st[N];
bool cmp(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}
ll dot(node a,node b){return 1ll*a.x*b.x+1ll*a.y*b.y;}
ll cross(node a,node b,node c){return 1ll*(a.x-c.x)*(b.y-c.y)-1ll*(a.y-c.y)*(b.x-c.x);}
void update(int L,int R,int id,int l,int r,int rt)
{
    if(L<=l&&r<=R){a[rt].push_back(p[id]);return;}
    int mid=l+r>>1;
    if(L<=mid)update(L,R,id,lson);
    if(R>mid)update(L,R,id,rson);
}
ll query(int id)
{
    int l=1,r=top,m1,m2;
    ll ret=0;
    while(r-l>=3)
    {
        m1=l+(r-l)/3,m2=r-(r-l)/3;
        if(dot(q[id],st[m1])<=dot(q[id],st[m2]))l=m1;else r=m2;
    }
    for(int i=l;i<=r;i++)ret=max(ret,dot(q[id],st[i]));
    return ret;
}
void work(int x,int l,int r)
{
    if(!a[x].size())return;
    top=0;
    sort(a[x].begin(),a[x].end(),cmp);
    for(int i=0;i<a[x].size();i++)
    {
        while(top>1&&cross(st[top-1],st[top],a[x][i])>=0)top--;
        st[++top]=a[x][i];
    }
    for(int i=l;i<=r;i++)ans[i]=max(ans[i],query(i));
}
void divide(int l,int r,int rt)
{
    work(rt,l,r);
    if(l==r)return;
    int mid=l+r>>1;divide(lson),divide(rson);
}
int main()
{
    scanf("%d",&n);
    for(int i=1,op,x,y;i<=n;i++)
    {
        scanf("%d%d",&op,&x);
        if(op==1)scanf("%d",&y),p[++tot]=(node){x,y,tim+1,-1};
        else if(op==2)p[x].r=tim;
        else scanf("%d",&y),q[++tim]=(node){x,y,tim,tim};
    }
    for(int i=1;i<=tot;i++)if(p[i].r==-1)p[i].r=tim;
    for(int i=1;i<=tot;i++)if(p[i].l<=p[i].r)update(p[i].l,p[i].r,i,1,tim,1);
    divide(1,tim,1);
    for(int i=1;i<=tim;i++)printf("%lld\n",ans[i]);
}

原文地址:https://www.cnblogs.com/hfctf0210/p/11044327.html

时间: 2024-10-03 08:37:27

bzoj4311向量(线段树分治+斜率优化)的相关文章

【BZOJ-3672】购票 树分治 + 斜率优化DP

3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1177  Solved: 562[Submit][Status][Discuss] Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的父亲用道路连接.为了方便起见,我们将全国的 n 个城市用 1 到 n 的整数编号.

【BZOJ3672】[Noi2014]购票 树分治+斜率优化

[BZOJ3672][Noi2014]购票 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的父亲用道路连接.为了方便起见,我们将全国的 n 个城市用 1 到 n 的整数编号.其中SZ市的编号为 1.对于除SZ市之外的任意一个城市 v,我们给出了它在这棵树上的父亲城市 fv  以及到父亲城市道路的长度 sv. 从城市 v 前往SZ市的方法为:选择城

线段树分治

2014徐寅展论文<线段树在一类分治问题上的应用>读后感. 线段树分治 线段树分治其实就是有撤销操作的时间分治. 题目让你维护一些信息,每次可以询问,可以执行一种操作,也可以将之前的某个这种操作撤回. 操作容易维护,但撤回操作不容易维护. 需要将操作,询问都离线下来.将时间轴画出来,那么每个操作只在时间轴上的一个区间内生效. 用线段树给这个区间打上这个操作的标记,维护信息. TJOI2018 数学计算 小豆现在有一个数x,初始值为1. 小豆有Q次操作,操作有两种类型: m: x = x * m

线段树分治总结

目录 类型一 例题1:八纵八横 代码: 例题2:时空旅行 首先,要求可以离线. 线段树分治有两种. 类型一 操作基于区间,单点询问. 有时,进行的一种操作可以快速完成,但是,要实现这种操作的逆操作较难. 因为,通常情况下,需要实现的逆操作都是很久以前执行的. 但是,如果只撤销上次操作,就会简单得多. 比如,维护一些连通性,或直径,线性基等问题. 这类问题加边很好做,但删边很难实现. 我们可以扫一遍操作,得到每个操作的有效区间. 然后,将每个添加操作的有效区间按在线段树上,然后遍历这颗线段树同时处

【uoj#244】[UER #7]短路 CDQ分治+斜率优化dp

题目描述 给出 $(2n+1)\times (2n+1)$ 个点,点 $(i,j)$ 的权值为 $a[max(|i-n-1|,|j-n-1|)]$ ,找一条从 $(1,1)$ 走到 $(2n+1,2n+1)$ 的路径,使得经过的点(包括起点和终点)权值和最小.求这个权值和. 输入 第一行一个正整数 $n$ . 第二行 $n+1$ 个正整数 $a[0],a[1],…,a[n]$ ,表示从内到外每层的中继器的延时值. 输出 输出一行一个数表示改造后的最短引爆时间. 样例输入 99 5 3 7 6 9

3237: [Ahoi2013]连通图 线段树分治

题解: 线段树分治裸题 apio t1是这个所以就学习了一下 #include <bits/stdc++.h> using namespace std; const int N=2e5+10; struct re{ int x,y; }a[N*2]; int b[N+20][5],cnt,now,n,m,k; int ls[N*15],rs[N*15],data[N*15],last[N+20]; int ph[N*4],pt[N*4],count2[N+20],f[N]; bool ft[N

线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)

闲话 stO猫锟学长,满脑子神仙DS 线段树分治思想 我们在做CDQ的时候,将询问和操作通通视为元素,在归并过程中统计左边的操作对右边的询问的贡献. 而在线段树分治中,询问被固定了.按时间轴确定好询问的序列以后,我们还需要所有的操作都会影响一个时间区间.而这个区间,毫无疑问正好对应着询问的一段区间. 于是,我们可以将每一个操作丢到若干询问里做区间修改了,而线段树可以高效地维护.我们开一个叶子节点下标为询问排列的线段树,作为分治过程的底层结构. 具体的实现,仍然要看题目. 例题1 BZOJ4025

算法学习——动态图连通性(线段树分治+按秩合并并查集)

在考场上遇到了这个的板子题,,,所以来学习了一下线段树分治 + 带撤销的并查集. 题目大意是这样的:有m个时刻,每个时刻有一个加边or撤销一条边的操作,保证操作合法,没有重边自环,每次操作后输出当前图下所有联通块大小的乘积. 首先观察到如果没有撤销操作,那么直接用并查集就可以维护,每次合并的时候乘上要合并的两个并查集大小的逆元,然后乘上合并之后的大小即可. 那么来考虑撤销,观察到如果并查集不带路径压缩,应该是可以处理撤销操作的. 但我们并不能直接做,因为并查集的撤销必须按顺序来,就相当于每次合并

【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个城市),保证任意两个城市都可以通过高速公路互达. 国正在筹划“八纵八横”的高铁建设计划,计划要修建一些高速铁路,每条高速铁路两端也都是城市(可能两端是同一个城市),也都有一个非负整数的经济影响因子.国家还计划在“八纵八横”计划建成之后,将“一带一路”扩展为“一带_路一