• 【题解】Interval [牛客


    题目链接

    题意

    • page15image35065504
    • 注意L可能大于R(应该都注意到了)

    题解

    • 对于固定的左端点或者右端点,不同的值至多只有log个
    • 先把这些值找出来,然后去掉具有包含关系的相同的值
    • 单纯的二维偏序求和无法处理相同的值
    • 那么把相同的值按顺序放在一起 (l1,r1)(l2,r2)...(lp,rp)
    • 那么如果查询包含了(l1,r2)(l2,r3)...(lp-1,rp)这些区间,答案就应该-1
    • 所以设置一些权值为-1的区间,再二维偏序即可

    总结

    对于一般的(离线)二维偏序问题,常常对第一维排序后,用树状数组维护第二维的值。

    而这道题中,需要解决的是强制在线的二维偏序问题,就需要用到主席树处理区间。

    多个根结点rt[i]代表不同的右区间,通过继承上一个根结点的信息,保证了其内部包括的区间的第二维只会是递增的。

    主席树此时等价于n棵线段树,查询操作相当于询问左区间个数之和,时间复杂度是log(n)的。

    代码

    #include <iostream>
    #include <map>
    using namespace std;
    const int N = 1e5 + 5;
    #define mid ((l+r)>>1)
    #define lson tr[o].l, l, mid
    #define rson tr[o].r, mid+1, r
    
    struct node {
       int sum, l, r;
    }tr[N*400];
    int tot = 0, rt[N]; // 空间开32倍RE了
    
    void update(int &o, int l, int r, int i, int v) {
       tr[++tot] = tr[o]; o = tot; tr[o].sum += v; // 继承上一个右区间的信息后,更新点权
       if(l == r) return;
       else if(i <= mid) update(lson, i, v);
       else update(rson, i, v);
    }
    
    int query(int o, int l, int r, int L, int R) {
       if(l > R || r < L) return 0;
       if(L <= l && r <= R) return tr[o].sum;
       return query(lson, L, R) + query(rson, L, R);
    }
    
    int main() {
       int n; scanf("%d", &n);
       map<int, int> pre, his;
       for (int i = 1; i <= n; i++) {
           int x; scanf("%d", &x);
           map<int, int> cur;
           pre[(1<<30)-1] = i; // 考虑当前节点构成区间
           for (auto o : pre) {
               int key = o.first & x;
               cur[key] = max(cur[key], o.second);
          }
           
           rt[i] = rt[i-1]; // 继承上一个右区间的信息
           for (auto o : cur) {
               if(his.count(o.first)) {
                   update(rt[i], 1, n, his[o.first], -1); // 去重
              }
               his[o.first] = o.second;
               update(rt[i], 1, n, o.second, 1);
          }
           
           swap(cur, pre);
      }
       
       int q;
       scanf("%d", &q);
       int last = 0;
       while (q--) {
           int l, r;
           scanf("%d %d", &l, &r);
           l = (l ^ last) % n + 1;
           r = (r ^ last) % n + 1;
           
           if(l > r) swap(l, r);
           last = query(rt[r], 1, n, l, r);
           printf("%d
    ", last);
      }
    }
    
  • 相关阅读:
    修改hosts文件
    什么时候集合不可以插入空值
    OL2中实现百度地图ABCD marker的效果
    OL3实现多图联动
    Arcgis for javascript实现百度地图ABCD marker的效果
    OL记载Arcgis Server切片
    postgis常用函数介绍(二)
    postgis常用函数介绍(一)
    共享个地图控件的样式
    OpenLayers3基础教程——OL3 介绍interaction
  • 原文地址:https://www.cnblogs.com/Waldeinsamkeit/p/13444902.html
Copyright © 2020-2023  润新知