zoukankan      html  css  js  c++  java
  • 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
    ",lasans);
            }
        }
        return 0;
    }
  • 相关阅读:
    Scala入门基础1
    LitePal数据库的基本操作
    Android操作SQLate数据库
    Android广播的使用(自定义广播和本地广播)
    Android广播的使用(动态注册和静态注册)
    Android碎片的使用
    linux--硬链接与软连接
    linux下python环境的搭建
    系统时间的修改
    linux命令--文件和目录管理
  • 原文地址:https://www.cnblogs.com/si--nian/p/11773523.html
Copyright © 2011-2022 走看看