• 线段相交的异或值 (线段树 or 优先队列)


    VVQ 最近迷上了线段这种东西

    现在他手上有 n 条线段,他希望在其中找到两条有公共点的线段,使得他们的异或值最大。 定义线段的异或值为它们并的长度减他们交的长度

    输入描述:

    第一行包括一个正整数 n,表示 VVQ 拥有的线段条数。
    接下来 n 行每行包括两个正整数 l,r,表示 VVQ 拥有的线段的 左右端点。

    输出描述:

    一行一个整数,表示能得到的最大异或值
    示例1

    输入

    3 
    10 100 
    1 50 
    50 100

    输出

    99

    说明

    选择第二条和第三条,99-0=99

    备注:

    1<=n<=200000,1<=l<=r<=1e8

    题意 : 在坐标轴上面有很多线段,问你所有有公共点的线段的异或值最大是多少?
    思路 : 所以线段只有 3 种情况, 1 是不相交, 2是相交, 3是包含,第一种情况的答案是 0, 对于第二种情况 假设2条线段i,j,且靠右的线段是 j,则此情况下的异或值是
    rj+lj-(ri+li),将 i 看成是不变的量,让 j线段的值最大即可,线段树维护就可以了, 对于第三种情况,答案是 (rj-lj)-(ri-li),则此时值需要让 ri-rl的值最小即可。
    代码示例 :
    #define ll long long
    const int maxn = 2e5+5;
    const int mod = 1e9+7;
    const double eps = 1e-9;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    #define lson k<<1
    #define rson k<<1|1
    
    struct edge
    {
        int l, r;
        bool operator< (const edge &v)const{
            return l < v.l;
        }
    }pre[maxn];
    
    struct node
    {
        int l, r;
        int mi,ma;
    }t[maxn<<2];
    
    void pushup(int k){
        t[k].ma = max(t[lson].ma, t[rson].ma);
        t[k].mi = min(t[lson].mi, t[rson].mi);
    }
    
    void build(int l, int r, int k){
        t[k].l = l;
        t[k].r = r;
        if (l == r){
            t[k].ma = pre[l].l+pre[l].r;
            t[k].mi = pre[l].r-pre[l].l;
            return;
        }
        int mid = (l+r) >> 1;
        build(l, mid, lson);
        build(mid+1, r, rson);
        pushup(k);
    }
    int sum = 0;
    void query(int l, int r, int k){
        if (l <= t[k].l && t[k].r <= r){
            sum = max(sum, t[k].ma);
            return;
        }
        int m = (t[k].l+t[k].r)>>1;
        if (l <= m) query(l, r, lson);
        if (r > m) query(l, r, rson);
    }
    
    void query2(int l, int r, int k){
        if (l <= t[k].l && t[k].r <= r){
            sum = min(sum, t[k].mi);
            return;
        }
        int m = (t[k].l+t[k].r)>>1;
        if (l <= m) query2(l, r, lson);
        if (r > m) query2(l, r, rson);
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int n;
        
        cin >>n;
        for(int i = 1; i <= n; i++){
            scanf("%d%d", &pre[i].l, &pre[i].r);
        }
        sort(pre+1, pre+1+n);
        build(1, n, 1);
        int ans = 0;
        edge tem;
        for(int i = 1; i <= n; i++){
            tem.l = pre[i].l;
            int p1 = lower_bound(pre+1, pre+1+n, tem)-pre;
            tem.l = pre[i].r;
            int p2 = upper_bound(pre+1, pre+1+n, tem)-pre-1; 
            sum = 0;
            //printf("p1 = %d p2 = %d
    ", p1, p2);
            query(p1, p2, 1);
            ans = max(ans, sum-(pre[i].l+pre[i].r));
            sum = inf;
            query2(p1, p2, 1);
            ans = max(ans, pre[i].r-pre[i].l-sum);
        }
        printf("%d
    ", ans);
        return 0;
    }
    

    方法二 : 优先队列(自己的超时了,先借鉴一个,待更新)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5+10;
    int n, m;
    
    struct P {
        int l, r;
        bool operator < (const P &t) const {
            return l + r > t.l + t.r;
        }
    } p[maxn];
    
    bool cmp(P a, P b) {
        return a.l == b.l ? a.r < b.r : a.l < b.l;
    }
    
    int main() {
        while(~scanf("%d", &n)) {
            for(int i = 0; i < n; i++) scanf("%d %d", &p[i].l, &p[i].r);
            sort(p, p + n, cmp);
            priority_queue<P> q;
            priority_queue<P> Q;
            q.push(p[0]);
            Q.push({p[0].l, -p[0].r});
            int ans = 0;
            for(int i = 1; i < n; i++) {
                while(!Q.empty() && -Q.top().r < p[i].l) Q.pop();
                if(!Q.empty() && -Q.top().r > p[i].r) ans = max(ans, -(Q.top().r + Q.top().l) - p[i].r + p[i].l);
                Q.push({p[i].l, -p[i].r});
                while(!q.empty() && q.top().r < p[i].l) q.pop();
                //p中所有点已按l排序,当前点与队列里第一个点不相交,后面的点一定不相交
                if(!q.empty()) ans = max(ans, p[i].l + p[i].r - q.top().l- q.top().r);
                q.push(p[i]);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    Apache+php显示错误信息
    Laravel 中的多组认证模式
    Laravel 如何在Blade模板中能够根据不同的子页面附加不同的js和CSS
    Laravel 数据库
    Laravel Middleware 中间件笔记
    Laravel Routing笔记
    Laravel 进阶任务笔记
    Laravel 基本任务笔记
    Laravel5 根目录router无效
    Fedora23 安装 psycopg2
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8781556.html
Copyright © 2020-2023  润新知