HDU4417-树状数组2012 ACM/ICPC Asia Regional Hangzhou Online

来源:互联网 发布:ubuntu 安装 kde桌面 编辑:程序博客网 时间:2024/05/16 19:07

题目:题目链接


这道题目的意思是给你一个数组。然后有m次询问。每次询问某个区间内小于给定值H的有多少?


典型的树状数组:

 
离线 树状数组 
1、若 a[i].h  > q[j].h,则从 i 以后的 a[i].h 也不会再对这个查询的解有影响。此时我们可以得到这个查询的解

 getsum(r) - getsum(l-1) 。 


2、若 a[i].h <= q[j].h,则它会且仅会对从 j 以后的每个 q[j].h 产生影响。于是我们需要在区间中对这个位置加

1,然后让 i 向后移动。


#include <iostream>#include <cstdio>#include <string>#include <string.h>#include <map>#include <vector>#include <cstdlib>#include <cmath>#include <algorithm>#include <queue>#include <set>#include <stack>using namespace std;const int N=100002;int d[N],ans[N],n;struct node{    int l,r,h,id;} q[N],p[N];int lowbit(int x){    return x&(-x);}int cmp(node a,node b){    return a.h<b.h;}void add(int x,int data){    for(; x<=n; x+=lowbit(x))        d[x]+=data;//注意这里的n不一定是数据量。可能是数据中最大的一个}int getsum(int x){    int ret=0;    for(; x; x-=lowbit(x))        ret+=d[x];    return ret;}int main(){    int t,m,i,j,cas=1;    cin >> t;    while(t--)    {        memset(d,0,sizeof(d));        scanf("%d%d",&n,&m);        for(int i=0; i<n; i++)        {            scanf("%d",&p[i].h);            p[i].id = i+1;        }        for(j=0; j < m; j++)        {            scanf("%d%d%d",&q[j].l,&q[j].r,&q[j].h);            q[j].id = j;        }        sort(p, p+n, cmp);        sort(q, q+m, cmp);        for(j=i=0; j<m; j++)        {            while(i < n && p[i].h <= q[j].h)            {                add(p[i].id,1);                i++;            }            ans[q[j].id] = getsum(q[j].r+1) - getsum(q[j].l);        }        printf("Case %d:\n",cas++);        for(j=0; j<m; j++)            printf("%d\n",ans[j]);    }    return 0;}

努力努力...

原创粉丝点击