• 洛谷P1533 可怜的狗狗题解


    本题可以使用权值线段树+离散化+二分解答

    首先观察题目,题目要求i-j区间之内的第k大的树

    所以我们可以用权值线段树,但是权值线段树只能在查找全局最大值,本题要求i-j区间的最大值

    所以我们考虑使用莫队算法,因为这道题我们看出可以离线查询,对每个询问进行查询记录

    另外这题数据大,所以使用离散化,具体注释看代码

    #include<bits/stdc++.h>
    #define N 300005
    using namespace std;
    int m,n,k;
    int a[N],b[N],u[N];
    int pos[N];
    int ans[N];
    struct MM{
        int l,r,s;
    }tr[N<<2];
    struct node{
        int l,r;
        int k;
        int id;
    }q[N];
    void build(int u,int L,int R){ 
        tr[u].l=L;
        tr[u].r=R;
        if(L==R) return;
        int mid=(L+R)>>1;
        build(u<<1,L,mid);
        build(u<<1|1,mid+1,R);
    }
    bool cmp(node a,node b){
        if(pos[a.l]==pos[b.l])
        return a.r<b.r;
        return pos[a.l]<pos[b.l];
    }
    inline void modify(int u,int t,int k){  //区间更改操作,找到我们需要修改的位置,单点修改 
        if(tr[u].l==tr[u].r){
            tr[u].s+=k;
            return;
        }
        int mid=(tr[u].l+tr[u].r)>>1;
        if(t<=mid) 
        modify(u<<1,t,k);
        else 
        modify(u<<1|1,t,k);
        tr[u].s=tr[u<<1].s+tr[u<<1|1].s;
    }
    inline int query(int u,int t){  //查询k小数,加入小于等于左边区间,就去左边区间找,否则去右边 
        if(tr[u].l==tr[u].r)
            return tr[u].l;
        if(t<=tr[u<<1].s) 
        return query(u<<1,t);
        else 
        return query(u<<1|1,t-tr[u<<1].s);  //注意减去左边区间的值,因为右边区间不包括左边的值 
    }
    int main(){
        cin>>n>>m;
        int block=sqrt(n); //分块 
        for(int i=1;i<=n;i++){
            cin>>a[i];
            pos[i]=(i-1)/block+1;
            b[i]=a[i];
        }
        for(int i=1;i<=m;i++){
         cin>>q[i].l>>q[i].r>>q[i].k;
          q[i].id=i;
        }
        sort(q+1,q+1+m,cmp);
        sort(b+1,b+n+1);   
        int s=unique(b+1,b+n+1)-(b+1);  //离散化模板 
        build(1,1,s);
        int l=1;
        int r=0;
        int i;
        for(i=1;i<=m;i++){  //莫队算法,本题莫队的add和sub函数可以用线段树的更新操作替代 
            while(q[i].l<l){
                int st=lower_bound(b+1,b+s+1,a[--l])-b;
                modify(1,st,1);
            }
            while(q[i].l>l){
                int st=lower_bound(b+1,b+s+1,a[l++])-b;
                modify(1,st,-1);
            }
            while(q[i].r>r){
                int st=lower_bound(b+1,b+s+1,a[++r])-b;
                modify(1,st,1);
            }
            while(q[i].r<r){
                int st=lower_bound(b+1,b+s+1,a[r--])-b;
                modify(1,st,-1);
            }
           ans[q[i].id]=b[query(1,q[i].k)];
        }
        for(i=1;i<=m;i++)
        cout<<ans[i]<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    竞赛题解
    学习笔记
    竞赛题解
    学习笔记
    竞赛题解
    竞赛题解
    竞赛题解
    「链接」原博客链接
    「杂录」THUWC 2020 游记
    「杂录」CSP-S 2019 爆炸记&题解
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12249693.html
Copyright © 2020-2023  润新知