zoukankan      html  css  js  c++  java
  • [BZOJ 4311] 向量

    题目

    传送门

    解法

    假设向量 ((x_2,y_2)) 对于询问 ((x,y)) 优于 ((x_1,y_1)),其中 (x_1<x_2)。那么有:

    [x_1x+y_1y<x_2x+y_2y ]

    [-frac{x}{y}<frac{y_2-y_1}{x_2-x_1} ]

    所以我们需要维护一个斜率递减的凸包。考虑三个点 (i<j<k),如果斜率递增,(j) 优于 (i)(k) 一定优于 (j),所以 (j) 是不必要的。

    维护每个向量的存在区间然后线段树分治。可以对于询问 ((x,y)) 在凸包上二分。也可以将询问按 (-frac{x}{y}) 从大到小排序,这个可以用归并排序。然后用双指针扫一遍就行了。

    时间复杂度 (mathcal O(nlog n))

    代码

    #include <cstdio>
    #define print(x,y) write(x),putchar(y)
    
    template <class T>
    inline T read(const T sample) {
    	T x=0; char s; bool f=0;
    	while((s=getchar())>'9' or s<'0')
    		f|=(s=='-');
    	while(s>='0' and s<='9')
    		x=(x<<1)+(x<<3)+(s^48),
    		s=getchar();
    	return f?-x:x;
    }
    
    template <class T>
    inline void write(const T x) {
    	if(x<0) {
    		putchar('-'),write(-x);
    		return;
    	}
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    }
    
    #include <vector>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int maxn=2e5+5;
    
    int n,m,tmp[maxn],tp;
    int p[maxn];
    ll ans[maxn];
    struct node {
    	int x,y,l,r;
    	
    	bool operator < (const node &t) const {
    		return x<t.x;
    	}
    } vec[maxn];
    struct Node {
    	int x,y;
    	
    	Node operator - (const Node &t) const {
    		return (Node){x-t.x,y-t.y};
    	}
    } q[maxn],stk[maxn];
    vector <Node> g[maxn<<2];
    
    void ins(int o,int l,int r,const node &v) {
    	if(l>v.r or r<v.l) return;
    	if(l>=v.l and r<=v.r)
    		return (void)(g[o].push_back((Node){v.x,v.y}));
    	int mid=l+r>>1;
    	ins(o<<1,l,mid,v);
    	ins(o<<1|1,mid+1,r,v);
    }
    
    ll dot(const Node &a,const Node &b) {
    	return 1ll*a.x*b.x+1ll*a.y*b.y;
    }
    
    ll cross(const Node &a,const Node &b) {
    	return 1ll*a.x*b.y-1ll*a.y*b.x;
    }
    
    void dicon(int o,int l,int r) {
    	if(l==r) {
    		p[l]=l;
    		for(int i=0;i<g[o].size();++i)
    			ans[l]=max(ans[l],dot(q[l],g[o][i]));
    		return;
    	}
    	int mid=l+r>>1;
    	dicon(o<<1,l,mid);
    	dicon(o<<1|1,mid+1,r);
    	int L=l,R=mid+1,pc=l;
    	while(L<=mid or R<=r) {
    		if(R>r or (L<=mid and cross(q[p[L]],q[p[R]])<=0))
    			tmp[pc++]=p[L++];
    		else tmp[pc++]=p[R++];
    	}
    	for(int i=l;i<=r;++i)
    		p[i]=tmp[i];
    	tp=0;
    	for(int i=0;i<g[o].size();++i) {
    		while(tp>1 and cross(stk[tp]-stk[tp-1],g[o][i]-stk[tp-1])>=0)
    			--tp;
    		stk[++tp]=g[o][i];
    	}
    	if(tp) {
    		for(int i=l,j=1;i<=r;++i) {
    			while(j<tp and dot(stk[j],q[p[i]])<dot(stk[j+1],q[p[i]]))
    				++j;
    			ans[p[i]]=max(ans[p[i]],dot(stk[j],q[p[i]]));
    		}
    	}
    }
    
    int main() {
    	int op,x,y;
    	for(int T=read(9);T;--T) {
    		op=read(9),x=read(9);
    		if(op==1) {
    			y=read(9);
    			vec[++n]=(node){x,y,m+1,-1};
    		}
    		else if(op==2) {
    			vec[x].r=m;
    		}
    		else {
    			y=read(9);
    			q[++m]=(Node){x,y};
    		}
    	}
    	sort(vec+1,vec+n+1);
    	for(int i=1;i<=n;++i) {
    		if(vec[i].r==-1)
    			vec[i].r=m;
    		if(vec[i].l<=vec[i].r)
    			ins(1,1,m,vec[i]);
    	}
    	dicon(1,1,m);
    	for(int i=1;i<=m;++i)
    		print(ans[i],'
    ');
    	return 0;
    }
    
  • 相关阅读:
    Eclipse 导入项目乱码问题(中文乱码)
    sql中视图视图的作用
    Java基础-super关键字与this关键字
    Android LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)的参数理解
    Android View和ViewGroup
    工厂方法模式(java 设计模式)
    设计模式(java) 单例模式 单例类
    eclipse乱码解决方法
    No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案
    【转】使用 Eclipse 调试 Java 程序的 10 个技巧
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15203825.html
Copyright © 2011-2022 走看看