• [BZOJ3533][SDOI2014]向量集


    bzoj
    luogu

    description

    维护一个向量集,支持在末尾插入一个向量,以及询问([l,r])个插入的向量与((x,y))点积的最大值。强制在线。

    sol

    ((x,y))点积最大的向量一定在凸包上。
    所以可以维护区间的上凸壳与下凸壳。
    用线段树的方式实现:每插满线段树上的一个区间,就利用两个儿子的凸壳归并建出这个区间的凸壳。查询的话直接在凸壳上二分。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    #define ll long long
    const int N = 4e5+5;
    struct point{
    	int x,y;
    	point(){x=y=0;}
    	point(int _x,int _y){x=_x,y=_y;}
    	bool operator < (point b)
    		{return x<b.x||(x==b.x&&y<b.y);}
    	point operator - (point b)
    		{return point(x-b.x,y-b.y);}
    	ll operator * (point b)
    		{return (ll)x*b.y-(ll)y*b.x;}
    };
    ll dot(point a,point b){
    	return (ll)a.x*b.x+(ll)a.y*b.y;
    }
    vector<point>q1[N<<2],q2[N<<2];int m;ll ans;
    void modify(int x,int l,int r,point p){
    	if (l==r){
    		q1[x].push_back(p);q2[x].push_back(p);
    		return;
    	}
    	int mid=l+r>>1;
    	if (m<=mid) modify(x<<1,l,mid,p);else modify(x<<1|1,mid+1,r,p);
    	if (m<r) return;
    	int u=q1[x<<1].size(),v=q1[x<<1|1].size(),t=-1;
    	for (int i=0,j=0;i<u||j<v;)
    		if (i<u&&(j==v||q1[x<<1][i]<q1[x<<1|1][j])){
    			point tmp=q1[x<<1][i++];
    			while (t>0&&(q1[x][t]-q1[x][t-1])*(tmp-q1[x][t])>=0) --t,q1[x].pop_back();
    			++t,q1[x].push_back(tmp);
    		}else{
    			point tmp=q1[x<<1|1][j++];
    			while (t>0&&(q1[x][t]-q1[x][t-1])*(tmp-q1[x][t])>=0) --t,q1[x].pop_back();
    			++t,q1[x].push_back(tmp);			
    		}
    	u=q2[x<<1].size(),v=q2[x<<1|1].size(),t=-1;
    	for (int i=0,j=0;i<u||j<v;)
    		if (i<u&&(j==v||q2[x<<1][i]<q2[x<<1|1][j])){
    			point tmp=q2[x<<1][i++];
    			while (t>0&&(q2[x][t]-q2[x][t-1])*(tmp-q2[x][t])<=0) --t,q2[x].pop_back();
    			++t,q2[x].push_back(tmp);
    		}else{
    			point tmp=q2[x<<1|1][j++];
    			while (t>0&&(q2[x][t]-q2[x][t-1])*(tmp-q2[x][t])<=0) --t,q2[x].pop_back();
    			++t,q2[x].push_back(tmp);
    		}
    }
    void calc(int x,point p){
    	if (p.y>0){
    		int l=1,r=q1[x].size()-1,res=0;
    		while (l<=r){
    			int mid=l+r>>1;
    			if (dot(q1[x][mid],p)>dot(q1[x][mid-1],p)) res=mid,l=mid+1;
    			else r=mid-1;
    		}
    		ans=max(ans,dot(q1[x][res],p));
    	}else{
    		int l=1,r=q2[x].size()-1,res=0;
    		while (l<=r){
    			int mid=l+r>>1;
    			if (dot(q2[x][mid],p)>dot(q2[x][mid-1],p)) res=mid,l=mid+1;
    			else r=mid-1;
    		}
    		ans=max(ans,dot(q2[x][res],p));
    	}
    }
    void query(int x,int l,int r,int ql,int qr,point p){
    	if (l>=ql&&r<=qr) {calc(x,p);return;}
    	int mid=l+r>>1;
    	if (ql<=mid) query(x<<1,l,mid,ql,qr,p);
    	if (qr>mid) query(x<<1|1,mid+1,r,ql,qr,p);
    }
    int dc(int x){return x^(ans&0X7FFFFFFF);}
    int main(){
    	int q=gi(),Type=getchar()!='E';
    	while (q--){
    		char op=getchar();while(op!='A'&&op!='Q')op=getchar();
    		if (op=='A'){
    			int x=gi(),y=gi();if (Type) x=dc(x),y=dc(y);
    			++m;modify(1,1,400000,point(x,y));
    		}else{
    			int x=gi(),y=gi(),l=gi(),r=gi();
    			if (Type) x=dc(x),y=dc(y),l=dc(l),r=dc(r);
    			ans=-1ll<<60;query(1,1,400000,l,r,point(x,y));
    			printf("%lld
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    solr服务中集成IKAnalyzer中文分词器、集成dataimportHandler插件
    Solr_全文检索引擎系统
    MySQL设置字段的默认值为当前系统时间
    mybatis_常用标签
    mybatis_映射查询
    Vue核心知识——computed和watch的细节全面分析
    nrm的安装与使用
    Windows下安装及使用NVM
    github仓库添加MIT许可
    ES6——箭头函数与普通函数的区别
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9468824.html
Copyright © 2020-2023  润新知