zoukankan      html  css  js  c++  java
  • LOJ #2585. 「APIO2018」新家

    #2585. 「APIO2018」新家

    https://loj.ac/problem/2585

    分析:

      线段树+二分。

      首先看怎样数颜色,正常的时候,离线扫一遍右端点,每次只记录最右边的点,然后查询左端点,这里不太行。这里只需要统计是否全出现过,pre[i]为这个颜色的上一个位置,那么这也就说明了pre[i]+1这段区间没出现过,所以要求[r+1,n]这段区间的最小的pre都要大于等于l。于是这就是线段树区间查询最小值了。

      注意的是,每个点的pre有多个,每个叶子节点包含一个set,把所有的值插入进去,取最小值。用两个堆维护也可以,(取最小值,删除一个值)。

      然后就可以二分一个长度,然后查询[x-len,x+len]这段区间是否都有所有的颜色就行了。复杂度$O(nlog^2n)$

      一个log的做法,二分的过程放到了线段树上。  

    代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<cmath>
      6 #include<cctype>
      7 #include<set>
      8 #include<queue>
      9 #include<vector>
     10 #include<map>
     11 using namespace std;
     12 typedef long long LL;
     13 
     14 inline int read() {
     15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     17 }
     18 
     19 const int N = 300005;
     20 const int INF = 1e9;
     21 
     22 struct Node{
     23     int opt, x, col, t;
     24     Node() {}
     25     Node(int a,int b,int c,int d) { opt = a, x = b, col = c, t = d; }
     26     bool operator < (const Node &A) const {
     27         return t == A.t ? opt > A.opt : t < A.t; // 如果时间相同,先加入,在询问,再删除 
     28     }
     29 }A[N * 3];
     30 struct Heap{
     31     priority_queue<int, vector<int>, greater<int> > q1, q2;
     32     int size() { return q1.size() - q2.size(); }
     33     void add(int x) { q1.push(x); }
     34     void del(int x) { q2.push(x); }
     35     int top() {
     36         while (!q2.empty() && q1.top() == q2.top()) q1.pop(), q2.pop();
     37         return q1.top();
     38     }
     39 //    multiset<int> s;
     40 //    int size() { return s.size(); }
     41 //    void add(int x) { s.insert(x); }
     42 //    void del(int x) { s.erase(s.find(x)); }
     43 //    int top() { return *s.begin(); }
     44 }H[N];
     45 multiset<int> S[N];
     46 int ans[N], Id[N * 30], ls[N * 30], rs[N * 30], Mn[N * 30];
     47 int n, k, m, Index_Heap, Index_Tree, Root, Now_Col;
     48 
     49 void update(int l,int r,int &rt,int p,int u,int v) {
     50     if (!rt) rt = ++Index_Tree;
     51     if (l == r) {
     52         if (!Id[rt]) Id[rt] = ++Index_Heap;
     53         Heap &now = H[Id[rt]];
     54         if (u) now.add(u);
     55         if (v) now.del(v);
     56         Mn[rt] = now.size() ? now.top() : INF;
     57         return ;
     58     }
     59     int mid = (l + r) >> 1;
     60     if (p <= mid) update(l, mid, ls[rt], p, u, v);
     61     else update(mid + 1, r, rs[rt], p, u, v);
     62     Mn[rt] = min(Mn[ls[rt]], Mn[rs[rt]]);
     63 }
     64 void add(const Node &now) {
     65     multiset<int> &s = S[now.col];
     66     multiset<int> :: iterator r = s.upper_bound(now.x), l = r; l--;
     67     update(0, INF, Root, *r, now.x, *l);
     68     update(0, INF, Root, now.x, *l, 0);
     69     if (s.size() == 2) Now_Col ++;
     70     s.insert(now.x);
     71 }
     72 void del(const Node &now) {
     73     multiset<int> &s = S[now.col];
     74     s.erase(s.find(now.x));
     75     if (s.size() == 2) Now_Col --;
     76     multiset<int> :: iterator r = s.upper_bound(now.x), l = r; l--;
     77     update(0, INF, Root, *r, *l, now.x);
     78     update(0, INF, Root, now.x, 0, *l);
     79 }
     80 int Ask(int p) {
     81     if (Now_Col != k) return -1;
     82     int l = 0, r = INF, now = Root, ans = INF;
     83     while (l != r) { // 模拟在线段树上走的过程 
     84         int mid = (l + r) >> 1, tmp = min(ans, Mn[rs[now]]); 
     85         if (p <= mid && tmp + mid >= p + p) ans = tmp, r = mid, now = ls[now];
     86         else l = mid + 1, now = rs[now];
     87     }
     88     return l - p;
     89 }
     90 int main() { 
     91     n = read(), k = read(), m = read();
     92     Mn[0] = INF;
     93     for (int i = 1; i <= k; ++i) // 初始往INF处加入k个-INF 
     94         S[i].insert(-INF), S[i].insert(INF), update(0, INF, Root, INF, -INF, 0); 
     95     int tot = 0;
     96     for (int i = 1; i <= n; ++i) {
     97         int x = read(), t = read(), a = read(), b = read();
     98         A[++tot] = Node(1, x, t, a); A[++tot] = Node(-1, x, t, b);
     99     }
    100     for (int i = 1; i <= m; ++i) {
    101         int x = read(), t = read();
    102         A[++tot] = Node(0, x, i, t);
    103     }
    104     sort(A + 1, A + tot + 1);
    105     for (int i = 1; i <= tot; ++i) {
    106         if (A[i].opt == 1) add(A[i]);
    107         else if (A[i].opt == -1) del(A[i]);
    108         else ans[A[i].col] = Ask(A[i].x);
    109     }
    110     for (int i = 1; i <= m; ++i) printf("%d
    ",ans[i]);
    111     return 0;
    112 }
  • 相关阅读:
    轻量级数据库sqlite的使用
    Integer引发的思考
    css限制显示行数
    数据库 chapter 17 数据仓库与联机分析处理技术
    数据库 chapter 15 对象关系数据库系统
    数据库 chapter 16 XML数据库
    数据库 chapter 14 分布式数据库系统
    数据库 chapter 11 并发控制
    数据库 chapter 12 数据库管理系统
    数据库 chapter 13 数据库技术新发展
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10063513.html
Copyright © 2011-2022 走看看