• [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;
    }
    
  • 相关阅读:
    2019南京网络赛 D Robots 期望dp
    【ICPC2019银川站】K
    【ICPC2019南昌站】I
    【SEERC 2019】E
    电子取证知识和经验总结
    CCPC2020绵阳站游记
    【CCPC2020绵阳站】J
    【CCPC2020绵阳站】K
    【SWERC 2019-20】K Birdwatching
    【HAOI2012】容易题
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15203825.html
Copyright © 2020-2023  润新知