HDU-4417:Super Mario(树状数组+离线操作)

来源:互联网 发布:前瞻网数据库免费账号 编辑:程序博客网 时间:2024/06/15 18:08


题目链接:点击打开链接


题目大意:

给你一些数,然后问你L R区间有多少数小于h,淦,明明马里奥撞过的砖就撞不了了,这道题为啥还能继续撞。。。


解题思路:

额,刚开始理解错了题意,然后就没有做出来。。。后来看了大佬的博客,发现这个离线操作是真的强。。。

总体上就是先把所有的数按照从大到小排序,然后再把所有的查询从大到小排序,然后每次对于最小的 x ,判断他是否小于当前查询的h,如果小于的话就加入树状数组。直到不满足这个条件,计算当前查询区间有多少个数,然后进行下一次查询。最后按照查询的顺序再输出一遍即可。细节看代码,


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define rank ra#define lson rt<<1#define rson rt<<1|1#define pb push_backusing namespace std;typedef long long ll;int n,m;int cnt[100010];int ans[100010];    //保存答案struct no1{    int idx;    int x;}a[100010];struct node{    int l,r;    int h;    int idx;}qu[100010];bool cmp1(no1 p,no1 q){    return p.x<q.x;}bool cmp2(node p,node q){    return p.h<q.h;}void add(int x)     //正常的树状数组{    while(x<=n)    {        cnt[x]++;        x += x&(-x);    }}int sum(int i){    int s=0;    while(i>0)    {        s+=cnt[i];        i -= i&(-i);    }    return s;}int main(){    int QAQ;    scanf("%d",&QAQ);    int kase=0;    while(QAQ--)    {        memset(cnt,0,sizeof(cnt));        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i].x);            a[i].idx=i;        }        int l,r,h;        for(int i=1;i<=m;i++)        {            scanf("%d%d%d",&l,&r,&h);            qu[i].l=l+1;       //记得加1            qu[i].r=r+1;            qu[i].idx=i;            qu[i].h=h;        }        sort(a+1,a+1+n,cmp1);        sort(qu+1,qu+1+m,cmp2);        printf("Case %d:\n",++kase);        for(int i=1,j=1;j<=m;j++)   //按照查询的h依次加入        {            while(i<=n&&qu[j].h>=a[i].x)            {                add(a[i].idx);                i++;            }            ans[qu[j].idx]=sum(qu[j].r)-sum(qu[j].l-1);        }        for(int i=1;i<=m;i++)            printf("%d\n",ans[i]);    }    return 0;}




阅读全文
0 0
原创粉丝点击