洛谷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

 

posted @ 2020-02-01 19:28  朝暮不思  阅读(142)  评论(0编辑  收藏  举报