• CF522D Closest Equals (线段树+思维)


    这题要求求区间内的一个值,我们可以联想到用线段树维护区间,这样查找的复杂度低

    这道题的难点不是线段树,而是我们应该维护哪个值,因为我们要求去的是l-r中ax和ay相等的最小距离,由此我们可以维护在当前位置前与他相等的最近的值是哪个位置,没有就是0

    因此只需要遍历的时候用map维护pre值即可,但是本题又出现一个问题,必须要在l-r之内,因此我们可以对询问按l排序,进行离线,然后对不满足条件的进行删除。

    #include<iostream>
    #include<map>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int N=5e5+10;
    const int inf=0x3f3f3f3f;
    int pre[N],nxt[N];
    int a[N];
    int ans[N];
    map<int,int> m1;
    struct node{
        int l,r;
        int cnt;
    }tr[N<<2];
    struct qi{
        int l,r;
        int id;
        bool operator <(const qi&t) const{
            return l<t.l;
        }
    }q[N];
    void pushup(int u){
        tr[u].cnt=min(tr[u<<1].cnt,tr[u<<1|1].cnt);
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]=(node){l,r};
            if(pre[l])
                tr[u].cnt=l-pre[l];
            else
                tr[u].cnt=inf;
        }
        else{
            tr[u]=(node){l,r};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
            pushup(u);
        }
    }
    void modify(int u,int x){
        if(tr[u].l==tr[u].r){
            tr[u].cnt=inf;
            return ;
        }
        int mid=tr[u].l+tr[u].r>>1;
        if(x<=mid)
            modify(u<<1,x);
        else
            modify(u<<1|1,x);
        pushup(u);
    }
    int query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r)
            return tr[u].cnt;
        int mid=tr[u].l+tr[u].r>>1;
        int res=inf;
        if(l<=mid)
            res=query(u<<1,l,r);
        if(r>mid)
            res=min(res,query(u<<1|1,l,r));
        return res;
    }
    int main(){
        int n,m;
        cin>>n>>m;
        int i;
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(m1[a[i]]){
                pre[i]=m1[a[i]],nxt[m1[a[i]]]=i,m1[a[i]]=i;
            }
            else{
                pre[i]=0,m1[a[i]]=i;
            }
        }
        for(i=1;i<=m;i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        sort(q+1,q+1+m);
        build(1,1,n);
        int pos=1;
        for(i=1;i<=m;i++){
            int l=q[i].l;
            int j;
            for(;pos<l;pos++){
                if(nxt[pos]>=l){
                    modify(1,nxt[pos]);
                }
    
            }
            ans[q[i].id]=query(1,q[i].l,q[i].r);
        }
        for(i=1;i<=m;i++){
            if(ans[i]==inf)
                printf("-1
    ");
            else
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    数字麦克风PDM信号采集与STM32 I2S接口应用(四)--单片机源码
    Golang SQL连接池梳理
    Ghost-无损DDL
    蛮好用的网站
    齿轮
    water
    折纸 (模拟)
    不等式(数学)
    周期串查询
    大集训模拟赛十一
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12542703.html
Copyright © 2020-2023  润新知