小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

[bzoj4311] 向量

 印度阿三17 2019-08-16

Description

你要維護一個向量集合,支持以下操作:
1.插入一個向量 \((x,y)\)
2.刪除插入的第 \(i\) 個向量
3.查詢當前集合與 \((x,y)\) 點積的最大值是多少。如果當前是空集輸出 \(0\)

Input

第一行輸入一個整數(shù) \(n\) ,表示操作個數(shù)
接下來 \(n\) 行,每行先是一個整數(shù) \(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 \leq 200000\) \(1 \leq x,y \leq 10^6\)


想法

每個向量只對一定范圍內(nèi)的查詢操作可能有貢獻,于是可以線段樹分治。

具體就是將詢問按時間編號為 \(1~m\) ,建一棵線段樹。
每個向量 \(insert\) 到它有貢獻的區(qū)間中,注意找到完全包含在它的貢獻區(qū)間的節(jié)點后打上標記就行了,不需要下放
怎么打標記呢?就是對每個節(jié)點開一個 \(vector\) ,把向量扔進去就行了。

接著我們考慮,“求集合中與\((x,y)\) 點積的最大值” 怎么搞。
對于集合中的兩個向量,\((u1,v1) 和 (u2,v2)\) ,不妨設(shè) \(u1<u2\)
若前者不如后者,即 \((u1,v1) \cdot (x,y) < (u2,v2) \cdot (x,y)\)
打開并整理一下得出 \(-\frac{x}{y} < \frac{v2-v1}{u2-u1}\)
也就是說我們需要維護斜率遞減的凸包。

為了維護方便,我們將向量們按 \(x\) 坐標從小到大依次 \(insert\) 到線段樹中,線段樹的每個節(jié)點維護一個凸包。
最終查詢的時候,在線段樹上從根到特定葉子的路徑上每個節(jié)點維護的凸包中二分最優(yōu)解,更新答案。
每次查詢復雜度 \(O(log^2n)\) , 總復雜度 \(O(nlog^2n)\)


代碼

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
 
using namespace std;
 
int read(){
    int x=0;
    char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=x*10 ch-'0',ch=getchar();
    return x;
}
 
const int N = 200005;
typedef long long ll;
 
int tot,n,m;
struct data{ int x,y,l,r; }d[N],q[N];
bool cmp(data x,data y) { return x.x<y.x; }
 
int root,cnt;
int ch[N*2][2];
vector<data> v[N*2];
void build(int x,int l,int r){
    if(l==r) return;
    int mid=(l r)>>1;
    build(ch[x][0]=  cnt,l,mid);
    build(ch[x][1]=  cnt,mid 1,r);
}
bool bigk(data a,data b,data c) { return 1ll*(b.y-a.y)*(c.x-b.x)<=1ll*(c.y-b.y)*(b.x-a.x); }
void ins(int x,int l,int r,int L,int R,int c){
    if(l==L && r==R){ 
        while(v[x].size()>1 && bigk(v[x][v[x].size()-2],v[x][v[x].size()-1],d[c])) v[x].pop_back();
        v[x].push_back(d[c]);
        return;
    }
    int mid=(l r)>>1;
    if(R<=mid) ins(ch[x][0],l,mid,L,R,c);
    else if(L>mid) ins(ch[x][1],mid 1,r,L,R,c);
    else{
        ins(ch[x][0],l,mid,L,mid,c);
        ins(ch[x][1],mid 1,r,mid 1,R,c);
    }
}
bool check(data a,data b,data c) { return 1ll*c.y*(a.y-b.y)<1ll*c.x*(b.x-a.x); }
ll ask(int x,int l,int r,int c){
    ll ret=0;
    if(v[x].size()>=1){
        int L=0,R=v[x].size()-1,mid;
        while(L<R){
            mid=(L R)>>1;
            if(check(v[x][mid],v[x][mid 1],q[c])) L=mid 1;
            else R=mid;
        }
        ret=1ll*q[c].x*v[x][L].x 1ll*q[c].y*v[x][L].y;
    }
     
    if(l==r) return ret;
    int mid=(l r)>>1;
    if(c<=mid) return max(ret,ask(ch[x][0],l,mid,c));
    return max(ret,ask(ch[x][1],mid 1,r,c));
}
 
int main()
{
    int Q,t,id,x,y;
    Q=read();
    while(Q--){
        t=read();
        if(t==1) {
            x=read(); y=read();
            d[  m]=(data){x,y,n 1,-1};
        }
        else if(t==2){
            id=read();
            d[id].r=n;
        }
        else {
            x=read(); y=read();
            q[  n]=(data){x,y,0,0};
        }
    }
    for(int i=1;i<=m;i  ) if(d[i].r==-1) d[i].r=n;
    sort(d 1,d 1 m,cmp);
     
    build(root=  cnt,1,n);
    for(int i=1;i<=m;i  )
        if(d[i].l<=d[i].r) ins(root,1,n,d[i].l,d[i].r,i);
     
    for(int i=1;i<=n;i  ) printf("%lld\n",ask(root,1,n,i));
     
    return 0;
} 
?
來源:https://www./content-4-394651.html

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章