GMOJ6282 向量

题意大概是动态维护一堆向量 每次求和一个给定向量的点积最大值

sol:
把点积的式子转化一下,可以转化成一个直线的形式

然后就发现题目求的其实是一堆直线的截距的最大

这东西动态维护一个凸包能解决

开个线段树即可

为了保证复杂度 只在节点满的时候建立凸包

没了。

#include <bits/stdc++.h>
using namespace std;
struct Node{
    long long x,y;
    Node () {}
    Node(long long a,long long b){x=a,y=b;}
    long long operator *(const Node &a) const {return x*a.y-y*a.x;}
    long long operator ^(const Node &a) const{return x*a.x+y*a.y;}
    Node operator -(const Node &a)const {return Node(x-a.x,y-a.y);}
    bool operator <(const Node &a)const {return (x==a.x)?y<a.y:x<a.x;}
};
vector <Node> Tree[1600010],v1[1600010],v2[1600010];
void Insert(int Now,Node qwq,int l,int r,int pos){
    Tree[Now].push_back(qwq);    
    if (pos==r){
    
        sort(Tree[Now].begin(),Tree[Now].end());
        int i;
        for (i=0;i<=r-l;i++){
            while (v1[Now].size()>1&&((Tree[Now][i]-v1[Now][v1[Now].size()-1])*(v1[Now][v1[Now].size()-2]-v1[Now][v1[Now].size()-1]))>=0) v1[Now].pop_back();
            v1[Now].push_back(Tree[Now][i]);
            while (v2[Now].size()>1&&((Tree[Now][i]-v2[Now][v2[Now].size()-1])*(v2[Now][v2[Now].size()-2]-v2[Now][v2[Now].size()-1]))<=0) v2[Now].pop_back();
            v2[Now].push_back(Tree[Now][i]);
        }
    }
    if (l==r) return;
    int mid=(l+r)>>1;
    if (pos<=mid) Insert(Now<<1,qwq,l,mid,pos);
    else Insert(Now<<1|1,qwq,mid+1,r,pos);
}
long long query1(int L,int R,Node ned,int l,int r,int Now)
{
    //cout<<l<<" "<<r<<endl;
    if(L<=l&&r<=R){
        int LL=1,RR=v1[Now].size()-1,Mid,Ans = 0;
        //cout<<LL<<" "<<RR<<endl;
        while(LL<=RR){
            Mid=(LL+RR)>>1;
            if((ned^v1[Now][Mid])>(ned^v1[Now][Mid-1]))Ans=Mid,LL=Mid+1;
            else RR=Mid-1;
            //cout<<LL<<" "<<RR<<endl;
        }
        return ned^v1[Now][Ans];
    }
    int mid=(l+r)>>1;
    long long ans = -1ll << 62;
    if(L<=mid) ans=max(ans,query1(L,R,ned,l,mid,Now<<1));
    if(R>mid)  ans=max(ans,query1(L,R,ned,mid+1,r,Now<<1|1));
    return ans;
}
long long query2(int L,int R,Node ned,int l,int r,int Now)
{
    if(L<=l&&r<=R){
        int LL=1,RR=v2[Now].size()-1,Mid,Ans = 0;
        while(LL<=RR){
            Mid=(LL+RR)>>1;
            if((ned^v2[Now][Mid])>(ned^v2[Now][Mid-1])) Ans=Mid,LL=Mid+1;
            else RR=Mid-1;
        }
        return ned^v2[Now][Ans];
    }
    int mid=(l+r)>>1;
    long long ans = -1ll << 62;
    if(L<=mid) ans=max(ans,query2(L,R,ned,l,mid,Now<<1));
    if(R>mid)  ans=max(ans,query2(L,R,ned,mid+1,r,Now<<1|1));
    return ans;
}
int main(){
    freopen("vector.in","r",stdin);
    freopen("vector.out","w",stdout);
    int opt,tot=0;
    long long lasans=0;
    int Q;
    scanf("%d",&Q);
    for (int i=1;i<=Q;i++){
        Node a;
        scanf("%d%lld%lld",&opt,&a.x,&a.y);
        a.x^=lasans;
        a.y^=lasans;
        if (opt==1) Insert(1,a,1,Q,++tot);
        else{
            int l,r;
            scanf("%d%d",&l,&r);
            l^=lasans;
            r^=lasans; 
            if (a.y>0) lasans=query1(l,r,a,1,Q,1);
            else lasans=query2(l,r,a,1,Q,1);
            printf("%lld\n",lasans);
        }
    }
    return 0;
}

 

posted @ 2019-10-31 20:23  si_nian  阅读(181)  评论(0编辑  收藏  举报