HDU 4417 树状数组

来源:互联网 发布:域名重新定向 编辑:程序博客网 时间:2024/06/06 21:41

题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4417

题解:
按每次查询的h值将查询排序,然后将数字排序,因为每次查询第i个h值时,前i-1个h值都比第i个h值小,所以前i-1个h值插入的数字对后面没有影响。这里用到了树状数组求逆序的思想,树状数组求逆序数时第i个值保存的数字是前面i-1个数比i小的数字的个数,但是此时要求数字为0到n-1。

AC代码:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 100010;int n,m;int tree[MAXN];int ans[MAXN];struct node{    int l,r,h,no;}query[MAXN];struct number{    int h,no;}numbers[MAXN];int lowbit(int i){    return i&(-i);}void add(int i){    while(i <= n)    {        tree[i] ++ ;        i += lowbit(i);    }}bool cmp1(number a, number b){    return a.h < b.h;}bool cmp2(node a, node b){    return a.h < b.h;}int sum(int i){    int ans = 0;    while(i > 0)    {        ans += tree[i];        i -= lowbit(i);    }    return ans;}int main(){    int t;    scanf("%d",&t);    for(int cnt = 1; cnt <= t; cnt++)    {        memset(tree,0,sizeof(tree));        memset(ans,0,sizeof(ans));        scanf("%d %d",&n, &m);        for(int i = 1; i <= n; i++)        {            scanf("%d", &numbers[i].h);            numbers[i].no = i;        }        for(int i = 1; i <= m; i++)        {            scanf("%d %d %d", &query[i].l, &query[i].r, &query[i].h);            query[i].no = i;        }        sort(numbers+1, numbers+n+1, cmp1);        sort(query+1, query+m+1, cmp2);        int numcnt = 1;        for(int i = 1; i <= m; i++)        {            while(numcnt <= n && query[i].h >= numbers[numcnt].h)            {                add(numbers[numcnt++].no);            }            //printf("%d %d %d\n", query[i].r+1, query[i].l, query[i].no);           // printf("%d %d\n", sum(query[i].r + 1), sum(query[i].l));            ans[query[i].no] = sum(query[i].r+1) - sum(query[i].l);        }        printf("Case %d:\n", cnt);        for(int i = 1; i <= m; i++)        {            printf("%d\n", ans[i]);        }    }    return 0;}
0 0
原创粉丝点击