zoukankan      html  css  js  c++  java
  • CF853E Lada Malina【凸包,扫描线】

    给定 (n) 个点 (mathbf{f_i}) 带权 (a_i)(k) 个向量 (mathbf{v_i})(q) 次询问 (mathbf p)(t),求存在实数 (w_jin[-t,t]) 满足 (mathbf{f_i}+sum w_jmathbf{v_j}=mathbf p)(a_i) 之和。

    (2le kle 10)(1le nle 10^5)(|vx_i|,|vy_i|le 10^3)(|fx_i|,|fy_i|,|px|,|py|leq 10^9)(1leq a_ileq 10^9)(1leq t_ileq 10^5)


    后面的 (sum w_jmathbf{v_j}) 显然是一个凸包(Minkowski 和),但这个凸包咋求呢?

    (vx_i<0land vx_i=0lor vy_i<0) 则令 (mathbf{v_i}) 取反,令 (mathbf p=mathbf p-tsummathbf{v_j}),并移项得到 (mathbf{f_i}=mathbf p+sum w_jmathbf{v_j})(w_j) 的取值范围变为 ([0,2t]),此时直接把所有 (mathbf{v_j}) 按斜率排序,按从小到大的顺序从 (mathbf p) 开始加就是下凸壳,从大到小的顺序就是上凸壳。

    因为凸包的边只有 (2k) 条,所以可以拆成一堆底边与 (y) 轴平行,直角边在 (-infty) 的直角梯形,约束即为 (xin[l,r])(y-kxleq b),令 (y:=y-kx) 之后就是二维数点,对纵坐标扫描线,对横坐标离散化之后用树状数组维护即可。

    注意扫描线做相同纵坐标时的顺序(先询问还是先修改),时间复杂度 (O((n+q)klog n))

    #include<bits/stdc++.h>
    #define MP make_pair
    #define PB emplace_back
    #define all(x) x.begin(), x.end()
    #define fi first
    #define se second
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int N = 100010;
    int rd(){
    	int ch = getchar(), x = 0; bool f = false;
    	for(;ch < '0' || ch > '9';ch = getchar()) f |= ch == '-';
    	for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
    	return f ? -x : x;
    }
    int k, n, q, sx, sy, x[N], y[N], a[N], px[N], py[N], t[N];
    pii v[11];
    LL ans[N], tr[N];
    vector<int> val;
    int pos(int x){return upper_bound(all(val), x) - val.begin();}
    struct Node {
    	double a;
    	int x, y, id;
    	Node(double _a = 0, int _x = 0, int _y = 0, int _z = 0): a(_a), x(_x), y(_y), id(_z){}
    	bool operator < (const Node &o) const {return fabs(a-o.a)<1e-7?id<o.id:a<o.a;}
    } w[N<<1];
    bool cmp(const pii &a, const pii &b){
    	if(!b.fi) return a.fi || a.se < b.se;
    	return a.se * b.fi < b.se * a.fi;
    }
    void upd(int p, int v){for(;p < N;p += p & -p) tr[p] += v;}
    LL qry(int p){LL r = 0; for(;p;p -= p & -p) r += tr[p]; return r;}
    int main(){
    	k = rd(); n = rd(); q = rd();
    	for(int i = 1;i <= k;++ i){
    		v[i].fi = rd(); v[i].se = rd();
    		if(v[i].fi < 0){
    			v[i].fi = -v[i].fi;
    			v[i].se = -v[i].se;
    		} else if(!v[i].fi && v[i].se < 0)
    			v[i].se = -v[i].se;
    		sx += v[i].fi; sy += v[i].se;
    	}
    	sort(v+1, v+k+1, cmp);
    	for(int i = 1;i <= n;++ i){
    		val.PB(x[i] = rd());
    		y[i] = rd(); a[i] = rd();
    	}
    	sort(all(val));
    	val.erase(unique(all(val)), val.end());
    	for(int i = 1;i <= q;++ i){
    		px[i] = rd(); py[i] = rd(); t[i] = rd();
    		px[i] -= sx*t[i]; py[i] -= sy*t[i]; t[i] <<= 1;
    	}
    	for(int i = 1;i <= k;++ i){
    		if(!v[i].fi){
    			for(int j = 1;j <= q;++ j)
    				py[j] += v[i].se * t[j];
    			continue;
    		}
    		double k = 1.*v[i].se/v[i].fi;
    		for(int j = 1;j <= n;++ j)
    			w[j] = Node(y[j] - k*x[j], x[j], a[j], 0);
    		for(int j = 1;j <= q;++ j){
    			w[n+j] = Node(py[j] - k*px[j], px[j], px[j] + v[i].fi*t[j], -j);
    			px[j] += v[i].fi*t[j]; py[j] += v[i].se*t[j]; 
    		}
    		sort(w+1, w+n+q+1); memset(tr, 0, sizeof tr);
    		for(int j = 1;j <= n+q;++ j)
    			if(w[j].id) ans[-w[j].id] -= qry(pos(w[j].y))-qry(pos(w[j].x-(i<2)));
    			else upd(pos(w[j].x), w[j].y);
    	}
    	for(int i = 1;i <= k;++ i){
    		if(!v[i].fi) break;
    		double k = 1.*v[i].se/v[i].fi;
    		for(int j = 1;j <= n;++ j)
    			w[j] = Node(y[j] - k*x[j], x[j], a[j], 0);
    		for(int j = 1;j <= q;++ j){
    			w[n+j] = Node(py[j] - k*px[j], px[j] - v[i].fi*t[j], px[j], j);
    			px[j] -= v[i].fi*t[j]; py[j] -= v[i].se*t[j];
    		}
    		sort(w+1, w+n+q+1); memset(tr, 0, sizeof tr);
    		for(int j = 1;j <= n+q;++ j)
    			if(w[j].id) ans[w[j].id] += qry(pos(w[j].y-(i>1))) - qry(pos(w[j].x-1));
    			else upd(pos(w[j].x), w[j].y);
    	}
    	for(int i = 1;i <= q;++ i) printf("%lld
    ", ans[i]);
    }
    
  • 相关阅读:
    动态规划(最长公共序列,最长上升序列)
    滴滴笔试--算术转移(20190827)
    线段树和树状数组
    pair和list学习
    数据结构--树(建立、遍历)
    tmux常用命令与快捷键
    机器学习实战-逻辑回归
    字符流中第一个重复的字符
    机器学习实战-朴素贝叶斯
    Python第三方库
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/14906122.html
Copyright © 2011-2022 走看看