• [BZOJ2687]交与并


    在 UNR 上看到这样一道题,当时想起来就是大视野原题,发现自己竟然没过,就刷了一波。

    [BZOJ2687]交与并

    试题描述

    对于一个区间集合 ({A_1,A_2,cdots,A_K}(K>1, forall i e j, A_i e A_j)),我们定义其权值 (W=|A_1 cup A_2 cup cdots cup A_K| cdot |A_1 cap A_2 cap cdots cap A_K|) 当然,如果这些区间没有交集则权值为 (0)

    输入

    给你 (N) 个((1<N le 10^6))各不相同的区间,请你从中找出若干个区间使其权值最大。

    第一行 (N),接下来(N)(l r(1 le l<r le 10^6))

    输出

    最大权值。

    输入示例

    4
    1 6
    4 8
    2 7
    3 5
    

    输出示例

    24
    

    数据规模及约定

    见“输入

    题解

    显然只有两个区间有意义。因为首先可以把被包含的区间去掉,然后按照左端点排序,那么答案等于我选择的所有区间中最靠左的和最靠右的答案。

    假设两个区间 (i)(j)(假设 (j)(i) 左,且两区间有交),答案就是 ((r_i - l_j)(r_j - l_i) = r_i r_j - l_i r_i - l_j r_j + l_i l_j),读者不妨自己证明这个 (j ightarrow i) 随着 (i) 往右,最优的 (j) 满足决策单调性。

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
    #define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)) { if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 1000010
    #define pii pair <int, int>
    #define x first
    #define y second
    #define mp(x, y) make_pair(x, y)
    #define LL long long
    
    int n, N;
    pii _lr[maxn], lr[maxn];
    
    LL calc(pii a, pii b) { return (LL)(max(a.y, b.y) - min(a.x, b.x)) * (min(a.y, b.y) - max(a.x, b.x)); }
    const bool cmp(const pii &a, const pii &b) { return a.x != b.x ? a.x < b.x : a.y > b.y; }
    const bool wrap(const pii &a, const pii &b) { return (a.x <= b.x && b.y < a.y) || (a.x < b.x && b.y <= a.y); }
    
    struct Info {
    	int l, r, p;
    	Info(int _1 = 0, int _2 = 0, int _3 = 0): l(_1), r(_2), p(_3) {}
    } S[maxn];
    int hd, top;
    LL ans;
    
    int main() {
    	n = read();
    	rep(i, 1, n) _lr[i].x = read(), _lr[i].y = read();
    	
    	sort(_lr + 1, _lr + n + 1, cmp);
    	lr[++N] = _lr[1];
    	rep(i, 2, n) if(_lr[i].y > lr[N].y) lr[++N] = _lr[i]; else ans = max(ans, calc(lr[N], _lr[i]));
    	S[hd = top = 1] = Info(2, N, 1);
    	rep(i, 2, N) {
    		while(hd < top && i > S[hd].r) hd++;
    		ans = max(ans, calc(lr[S[hd].p], lr[i]));
    		while(top > hd && calc(lr[i], lr[S[top].l]) >= calc(lr[S[top].p], lr[S[top].l])) top--;
    		int l = i + 1, r = N;
    		while(l < r) {
    			int mid = l + r >> 1;
    			if(calc(lr[S[top].p], lr[mid]) > calc(lr[i], lr[mid])) l = mid + 1; else r = mid;
    		}
    		if(calc(lr[S[top].p], lr[l]) > calc(lr[i], lr[l])) continue;
    		S[top+1] = Info(l, N, i);
    		S[top].r = l - 1; ++top;
    	}
    	
    	printf("%lld
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    通过JavaMail发送(群发)邮件示例(内含附件图片) 代码复制可用
    需要把获取系统的当前时间存入库里 获取时是String类型,库里是Datetime类型 String 转化 Date
    用canvas和原生js写的一个笨鸟先飞的小游戏(暂时只有一个关卡)
    Svg和canvas的区别,伪类选择器有哪些(归类)
    微信web网页动态增减输入框,搜索框,基于jQuery weui、jQuery 实现无限插入数据,动态数据生成,外加高德地图POI和根据坐标获取位置信息的页面
    vue 使用tinymce富文本编辑器
    mamp环境下navicat无法链接本地mysql
    tp5 系统变量输出
    开始项目注意事项
    jQuery weui实现下拉刷新事件
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/9314271.html
Copyright © 2020-2023  润新知