hdu 4417

来源:互联网 发布:面向切面编程面试 编辑:程序博客网 时间:2024/06/02 00:11

(离线+树状数组 | 主席树)
题意:给定n(n<105)个数ai(ai<109)m(m<105)个询问,每次询问求[l,r]区间里小于等于H(H<109)的数字有多少个?

思路1:我们将数组ai从小到大排序,并且将询问依据H从小到大进行排序。然后每次枚举到一个询问时,就往树状数组中插入所有小于当前询问里H的数字ai,这样区间查询的结果就是符合要求的。总之,这个思路用离线处理的方法固化了”小于H”这个条件,使得题目变成了树状数组的区间修改查询问题。
(注意写while语句插入ai的时候i不要越界)

思路2:主席树,待更

代码1:

#include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100010;int a[maxn], ans[maxn], tree[maxn];struct Num {    int num, pos;    Num(){}    Num(int a, int b):num(a),pos(b){}    bool operator < (const Num &A) const {        return num < A.num;    }}mynum[maxn];struct Query {    int id, l, r, mx;    Query(){}    Query(int a, int b, int c, int d):id(a),l(b),r(c),mx(d){}    bool operator < (const Query &A)const {        return mx < A.mx;    }}qu[maxn];int lowbit(int x) {    return x&(-x);}void update(int pos, int num) {    for(int i=pos; i<maxn; i+=lowbit(i))        tree[i] += num;}int get_sum(int pos) {    int ret = 0;    for(int i=pos; i>0; i-=lowbit(i))        ret += tree[i];    return ret;}int main() {    int T, n, m, cas = 0;    scanf("%d",&T);    while(T --) {        scanf("%d%d",&n,&m);        for(int i=1; i<=n; i++) {            scanf("%d",&a[i]);            mynum[i] = Num(a[i], i);        }        sort(mynum+1, mynum+n+1);        for(int i=1; i<=m; i++) {            int l, r, mx;            scanf("%d%d%d",&l,&r,&mx);            qu[i] = Query(i, l+1, r+1, mx);        }        sort(qu+1, qu+m+1);        memset(tree, 0, sizeof(tree));        int cur = 1;        for(int i=1; i<=m; i++) {            while(cur <= n && mynum[cur].num <= qu[i].mx) {                update(mynum[cur].pos, 1);                cur ++;            }            int tot = get_sum(qu[i].r) - get_sum(qu[i].l-1);            //printf("get : %d %d\n",get_sum(qu[i].r),get_sum(qu[i].l-1));            ans[qu[i].id] = tot;        }        printf("Case %d:\n",++cas);        for(int i=1; i<=m; i++)            printf("%d\n",ans[i]);    }    return 0;}
原创粉丝点击