2018 保研复试上机

题意:求区间L到R中大于等于a,并且小于等于b的数的数量。

思路:简单主席树。

#include <bits/stdc++.h>
using namespace std;
#define N 100005
#define mid ((l+r)>>1)
#define lc (tr[d].ch[0])
#define rc (tr[d].ch[1])

struct Tr{
    int cnt,ch[2];
}tr[N<<2];
int cnt = 0,ro[N];
int newnode(){
    ++cnt;
    tr[cnt].cnt = 0,tr[cnt].ch[0] = tr[cnt].ch[1] = 0;
    return cnt;
}
int build(int l,int r,int pre,int pos){
    int d = newnode();
    tr[d].cnt = tr[pre].cnt + 1;
    if(l == r) return d;
    lc = tr[pre].ch[0],rc = tr[pre].ch[1];
    if(pos <= mid)
        lc = build(l,mid,tr[pre].ch[0],pos);
    else rc = build(mid+1,r,tr[pre].ch[1],pos);
    return d;
}

int query(int l,int r,int L,int R,int ro1,int ro2){
    if(L == l && R == r){
        return tr[ro2].cnt - tr[ro1].cnt;
    }
    if(R <= mid) return query(l,mid,L,R,tr[ro1].ch[0],tr[ro2].ch[0]);
    if(L > mid) return query(mid+1,r,L,R,tr[ro1].ch[1],tr[ro2].ch[1]);
    return query(l,mid,L,mid,tr[ro1].ch[0],tr[ro2].ch[0]) + query(mid+1,r,mid+1,R,tr[ro1].ch[1],tr[ro2].ch[1]);
}

int main()
{
    int n,m;
    cin >> n >> m;
    int a,b;
    for(int i = 1;i <= n;++i) scanf("%d",&a),ro[i] = build(1,1000000,ro[i-1],a);
    int L,R;
    for(int i = 1;i <= m;++i){
        scanf("%d%d%d%d",&a,&b,&L,&R);
        printf("%d\n",query(1,1000000,a,b,ro[L-1],ro[R]));
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/solvit/p/9627426.html