codeforces 765 F 线段树+set

题意:多次询问区间内 两数差的绝对值的最小值

题解:离线询问则可以按照询问的l排序,倒着询问,倒着从r更新到l 每次更新i+1到n这个区间,保证这次的更新不会影响到下一次以及以后的更新。因为当两个区间出现覆盖时,l更小的那个区间的值一定小于等于另一个,画个图就可以明白。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cstring>
#include <iomanip>
#include <set>
#include<ctime>
#include<unordered_map>
//CLOCKS_PER_SEC
#define se second
#define fi first
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Pii pair<int,int>
#define Pli pair<ll,int>
#define ull unsigned long long
#define pb push_back
#define fio ios::sync_with_stdio(false);cin.tie(0)
const int N=1e6+10;
const ull base=163;
const int INF=0x3f3f3f3f;
using namespace std;
struct node {
    set<int>s;
    int mi;
}T[N<<2];
struct que {
    int l,r,id;
}q[N<<2];
int a[N];
bool cmp(que a,que b){
    if(a.l==b.l&&a.r==b.r)return a.id<b.id;
    if(a.l==b.l)return a.r<=b.r;
    return a.l<b.l;
}
void build(int l,int r,int rt){
    T[rt].mi=INF;
    for(int i=l;i<=r;i++)T[rt].s.insert(a[i]);
    if(l==r)return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
int query(int l,int r,int rt,int L,int R){
    if(l>R||L>r)return INF;
    if(L<=l&&R>=r){
        return T[rt].mi;
    }
    int m=(l+r)>>1;
    return min(query(lson,L,R),query(rson,L,R));
}
void update(int l,int r,int rt,int L,int R,int v,int &mi){
    if(l>R||L>r)return ;
    if(l==r){
        T[rt].mi=min(T[rt].mi,abs(a[l]-v));
        mi=min(mi,T[rt].mi);
        return ;
    }
    set<int> &t=T[rt].s;
    auto p=t.lower_bound(v);
    if((p==t.end()||*p-v>=mi)&&(p==t.begin()||v-*(--p)>=mi)){
        mi=min(mi,query(l,r,rt,L,R));
        return ;
    }
    int m=(l+r)>>1;
    update(lson,L,R,v,mi);
    update(rson,L,R,v,mi);
    T[rt].mi=min(T[rt<<1].mi,T[rt<<1|1].mi);
}
int ans[N];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int m;scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    build(1,n,1);
    sort(q+1,q+1+m,cmp);
    for(int i=m,l=n;i>=0;i--){
        for(;l>=q[i].l;l--){
            int tmp=INF;
            update(1,n,1,l+1,n,a[l],tmp);
        }
        ans[q[i].id]=query(1,n,1,q[i].l,q[i].r);
    }
    for(int i=1;i<=m;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Mrleon/p/9097557.html

时间: 2024-11-01 12:39:55

codeforces 765 F 线段树+set的相关文章

CodeForces 46DParking Lot线段树

#include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include <qu

Codeforces 19D Points 线段树+set

题目链接:点击打开链接 线段树维护y值大于val的最小x值 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf

Codeforces 444C(线段树)

区间颜色不一致就更新到底,否则lazy标记 #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; #define lc l,m,index<<1 #define rc m+1,r,index<<1|1 #define N 100005 #define ll __int64 struct node { bool sa

F - One Occurrence CodeForces - 1000F (线段树+离线处理)

You are given an array aa consisting of nn integers, and qq queries to it. ii-th query is denoted by two integers lili and riri. For each query, you have to find any integer that occurs exactly once in the subarray of aa from index lili to index riri

Codeforces 316 E3 线段树

题目链接 题意 给定一个长度为\(n\)序列\(a\),需要支持如下操作 单点修改 对于区间\([l..r]\),求\(\sum_{i=0}^{r-l}f_i*a_{l+i}\),模\(10^9\),其中\(f\)是斐波那契数列,\(f_0=f_1=1\) 区间加 做法 建线段树,对于一个节点\([l..r]\),记 \[s_k=\sum_{i=0}^{r-l}f_{i+k}*a_{l+i}\] 存在以下性质 \[ \begin{align} &s_{k-2}+s_{k-1}\=&\sum

Codeforces 787D. Legacy 线段树优化建图+最短路

output standard output Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them. There are n planets in their universe numbered from 1 to n.

New Year and Old Subsequence CodeForces - 750E(线段树 + 矩阵)

New Year and Old Subsequence (CodeForces - 750E) 题意: 给出一个长度为\(N\)的数字串,\(q\)次询问.每次询问一段区间.在区间内删除尽量少的字符,使得区间内含有序列"\(2017\)",且不含有"\(2016\)". \(n,q<=200000\). 题解: 用\(01234\)五种状态分别表示"". "\(2\)"."\(20\)"."

Sum Queries? CodeForces - 1217E (线段树)

Sum Queries? CodeForces - 1217E (线段树) 题意: 定义一个集合为\(balanced\)的,当且仅当集合内数字之和的每个十进制位,都与集合中某个数该位相同.否则,称该集合为\(unbalanced\)的. 给定一个长度为\(n\)的序列,\(q\)次询问一个区间内数字之和最小的\(unbalanced\)集合,输出数字之和.若没有输出\(-1\). \(n,q<=200000\). 题解: 可以发现,如果存在\(unbalanced\)集合,那么最小的一定是只两

F - Problem F( 线段树 )

度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串.现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值.一个字符串的哈希值,由以下公式计算得到: H(s)=∏i≤len(s)i=1(Si?28) (mod 9973)SiSi代表 S[i] 字符的 ASCII 码. 请帮助度熊计算大字符串中任意一段的哈希值是多少. Input多组测试数据,每组测试数据第一行是一个正整数NN,代表询问的次数,第二行一个字符串,代表题目中的大字符串,接