zoukankan      html  css  js  c++  java
  • loj6504. 「雅礼集训 2018 Day5」Convex

    题意

    给出若干的点,满足每个点都在所有点形成的凸包上,且点((0, 0))在凸包内。
    若干次询问一段区间构成凸包的面积。

    题解

    考虑莫队。
    但是发现莫队在加入一个点的时候还要在当前凸包上找前驱和后继,这个复杂度有一个(log),难以优化。
    但是删除的时候,我们发现,如果我们维护一个凸包上的点的前驱后继的一个链表,是很方便删除的。
    所以需要一个只删除不插入的莫队,这相当于一个回滚莫队。
    这个回滚莫队只要有删除操作和撤销操作就好了。由于删除操作比较简单,撤销操作便容易实现。
    因此可以在(mathcal O(n sqrt n))的时间内解决此题。
    顺带复习下回滚莫队:先按左端点所在块排,左端点在同一个块内按照右端点排,每次询问完之后左指针回滚到询问左端点所在块的右边界。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1.5e5 + 10, BLO = 350;
    int n, m, id[N], pre[N], suf[N]; ll sum, ans[N];
    struct P {
    	int x, y;
    	bool operator < (const P &o) const {
    		return atan2(y, x) < atan2(o.y, o.x);
    	}
    	ll operator * (const P &o) const {
    		return (ll)x * o.y - (ll)o.x * y;
    	}
    } a[N];
    struct Q {
    	int l, r, id;
    	bool operator < (const Q &o) const {
    		return (l - 1) / BLO == (o.l - 1) / BLO ? r > o.r : l < o.l;
    	}
    } q[N];
    bool cmp (int x, int y) {
    	return a[x] < a[y];
    }
    void del (int x) {
    	int l = pre[x], r = suf[x];
    	sum -= a[l] * a[x] + a[x] * a[r] - a[l] * a[r];
    	suf[l] = r, pre[r] = l;
    }
    void udel (int x) {
    	int l = pre[x], r = suf[x];
    	sum += a[l] * a[x] + a[x] * a[r] - a[l] * a[r];
    	suf[l] = pre[r] = x;
    }
    int main () {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d%d", &a[i].x, &a[i].y), id[i] = i;
    	}
    	sort(id + 1, id + n + 1, cmp), id[0] = id[n];
    	for (int i = 1; i <= n; ++i) {
    		pre[id[i]] = id[i - 1], suf[id[i - 1]] = id[i];
    		sum += a[id[i - 1]] * a[id[i]];
    	}
    	for (int i = 1; i <= m; ++i) {
    		scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i;
    	}
    	sort(q + 1, q + m + 1);
    	for (int L = 1, R, i = 1, l = 1, r = n; i <= m; L = R + 1) {
    		R = min(n, L + BLO - 1);
    		for ( ; i <= m && q[i].l <= R; ++i) {
    			for ( ; r > q[i].r; del(r--));
    			for ( ; l < q[i].l; del(l++));
    			ans[q[i].id] = sum;
    			for ( ; l > L; udel(--l));
    		}
    		for ( ; r < n; udel(++r));
    		for ( ; l <= R; del(l++));
    	}
    	for (int i = 1; i <= m; ++i) {
    		printf("%lld
    ", ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    反黑战役之谁动了我的文件?
    poj 1611 The Suspects
    Effective C++ 条款44
    不说技术~那些有文化的人们所说的各大主义,其实百度上都有
    DDD~Unity在DDD中的使用
    DDD~领域层
    知方可补不足~SQL中的count命令的一些优化措施(百万以上数据明显)
    将不确定变为确定~感谢异或,是你让我彻底摆脱“否定式”
    php按照奖品百分比随机抽奖代码分析
    linux下Ftp环境的搭建
  • 原文地址:https://www.cnblogs.com/psimonw/p/12066091.html
Copyright © 2011-2022 走看看