• CodeForces 765 F Souvenirs 线段树


    Souvenirs

    题意:给你n个数, m次询问, 对于每次一次询问, 求出询问区间内绝对值差值的最小值。

    题解:先按查询的右端点从小到大sort一下,然后对于塞入一个数的时候, 就处理出所有左端点到目前位置的点, 然后查询。

    首先对于一个区间 [L,now] 和 另一个区间来说 [l+1,now] 来说, 左边这个区间的ans值一定是 <= 右边这个区间的 ans 值, 因为左边这个区间包含右边这个区间, 所以对于[1,now]这个区间来说,端点值左边的区间里的ans 一定 小于右边的 ans。

    然后具体操作是, 先建树, 对于每一个节点来说,都讲他包含的数都塞入这个节点, 再通过归并排序保证这些数是递增排列,并且将ans树的答案都设为INF。然后对所有的查询,离线操作, 按照右端点sort一下, 然后每次对于一个新的右端点, 我们去更新他们前面的所有左端点值, 同时我们更新前面区间的时候, 我们都先检查一下这个答案能不能更新里面的值, 如果不能就剪枝, 就剪枝, 然后如果要更新右部分区间的话,就先更新右部分,再更新左部分,因为每次更新完之后d就会变小, 所以如果先更新左边,可能会导致右边区间的答案没有更新。(d为每次更新遇到的最小的ans值, 因为是先往右边更新的, 然后更左边的区间一定包含右边的这个答案, 所以即使左边的答案能更新成小一点, 但是不能更小的时候, 更新了也没有意义, 因为会更小的答案在右边)。然后查询的时候直接查询这一段区间的答案就好了。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
     4 #define LL long long
     5 #define ULL unsigned LL
     6 #define fi first
     7 #define se second
     8 #define pb push_back
     9 #define lson l,m,rt<<1
    10 #define rson m+1,r,rt<<1|1
    11 #define max3(a,b,c) max(a,max(b,c))
    12 #define min3(a,b,c) min(a,min(b,c))
    13 typedef pair<int,int> pll;
    14 const int INF = 0x3f3f3f3f;
    15 const LL mod =  (int)1e9+7;
    16 const int N = 1e5 + 100;
    17 vector<int> vc[N<<2];
    18 int Min[N<<2];
    19 int a[N];
    20 int n;
    21 struct Node{
    22     int l, r;
    23     int id;
    24 }q[N*3];
    25 bool cmp(Node x1, Node x2){
    26     return x1.r < x2.r;
    27 }
    28 void Merge(int rt){
    29     int i = 0, j = 0;
    30     int l = rt*2, r = rt*2+1;
    31     int szl = vc[l].size(), szr = vc[r].size();
    32     while(i < szl && j < szr){
    33         if(vc[l][i] < vc[r][j]) vc[rt].pb(vc[l][i]), i++;
    34         else vc[rt].pb(vc[r][j]), j++;
    35     }
    36     while(i < szl) vc[rt].pb(vc[l][i]), i++;
    37     while(j < szr) vc[rt].pb(vc[r][j]), j++;
    38 }
    39 void Build(int l, int r, int rt){
    40     Min[rt] = INF;
    41     if(l == r){
    42         vc[rt].pb(a[l]);
    43         return ;
    44     }
    45     int m = l+r >> 1;
    46     Build(lson);
    47     Build(rson);
    48     Merge(rt);
    49 }
    50 int Query(int l, int r, int rt, int L, int R){
    51     if(L <= l && r <= R){
    52         return Min[rt];
    53     }
    54     int ret = INF, m = l+r >> 1;
    55     if(L <= m) ret = min(ret, Query(lson,L,R));
    56     if(m < R) ret = min(ret, Query(rson,L,R));
    57     return ret;
    58 }
    59 vector<int>::iterator it;
    60 void Update(int l, int r, int rt, int R, int v, int &d){
    61     if(l == r){
    62         Min[rt] = min(Min[rt], abs(v-vc[rt][0]));
    63         d = min(d, Min[rt]);
    64         return ;
    65     }
    66     it = lower_bound(vc[rt].begin(), vc[rt].end(), v);
    67     if((it == vc[rt].end() || *it-v >= d) && (it == vc[rt].begin() || v - *(--it) >= d)){
    68         d = min(d, Query(1, n, 1, l, R));
    69         return ;
    70     }
    71     int m = l+r >> 1;
    72     if(R > m) Update(rson,R,v,d);
    73     Update(lson,R,v,d);
    74     Min[rt] = min(Min[rt*2], Min[rt*2+1]);
    75 }
    76 int ans[N*3];
    77 int main(){
    78     scanf("%d", &n);
    79     for(int i = 1; i <= n; i++)  scanf("%d", &a[i]);
    80     Build(1,n,1);
    81     int m;
    82     scanf("%d", &m);
    83     for(int i = 1; i <= m; i++)  scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i;
    84     sort(q+1, q+1+m, cmp);
    85     int r = 1;
    86     int d;
    87     for(int i = 1; i <= m; i++){
    88         while(r < q[i].r) {
    89             d = INF;
    90             Update(1, n, 1, r, a[r+1], d);
    91             r++;
    92         }
    93         ans[ q[i].id ] = Query(1, n, 1, q[i].l, r);
    94     }
    95     for(int i = 1; i <= m; i++){
    96         printf("%d
    ", ans[i]);
    97     }
    98     return 0;
    99 }
    765F
  • 相关阅读:
    bzoj5137 [Usaco2017 Dec]Standing Out from the Herd
    bzoj2434 [Noi2011]阿狸的打字机
    【20181024T2】小C的序列【GCD性质+链表】
    【20181024T3】小C的宿舍【分治】
    【20181024T1】小C的数组【二分+dp】
    【20181023T2】行星通道计划【二维BIT】
    【20181023T1】战争【反向并查集】
    【20181020T1】蛋糕
    【20181019T2】硬币【矩阵快速幂优化DP】
    【20181019T3】比特战争【最小生成树思想】
  • 原文地址:https://www.cnblogs.com/MingSD/p/9084386.html
Copyright © 2020-2023  润新知