hdu4417(离线操作 + 树状数组)

题意:

给定一个长度为n的数组,有m次的查询,每次查询[a,b]区间里比H小的数有多少个?

由于n和m的取值范围为0到10的5次方,所以直接回答会超时,所以考虑先读入所有的查询操作,然后依次回答比H小的[a,b]区间里的数有多少个,

求和类似于求正序数的方法。

写法可以边插变查,也可以边查边插,边查边插简单些;

可是这道题从头wa到了尾,原因是add函数少打了等于号,扇自己一巴掌.

边插边查:

#include <iostream>
#include <cstdio>
#include <time.h>
#include <stdlib.h>
#include <cstring>
#include<algorithm>
#define maxn 110000
#define LL  int
using namespace std;
struct node
{
   LL value,id;
};
struct querynode
{
    LL L,R,H=-1,cnt;
};
node a[maxn];
querynode  que[maxn];
LL c[maxn];
LL N,M;
LL ans[maxn];
void init()
{
   memset(a,0,sizeof(a));
   memset(c,0,sizeof(c));
   memset(ans,0,sizeof(ans));
}

bool cmp1(node a,node b)
   {
       return a.value<b.value;
   }
bool cmp2(querynode a,querynode b)
{
        return a.H<b.H;
}
int inline lowbit(int x){
    return x & (-x);
}
void inline add(int x){
    while(x <= N){
       c[x]++;
       x += lowbit(x);
    }
}
int inline sum(int x){
    int s = 0;
    while(x > 0){
      s += c[x];
      x -= lowbit(x);
    }
    return s;
}

void  solve()
{
    int t=1;
    for(int i=1;i<=N;i++)
    {
            if(que[t].H==-1)
            {
                break;
            }
            while(que[t].H<a[i].value && que[t].H!=-1)
            {
                ans[ que[t].cnt ]=sum(que[t].R)-sum(que[t].L-1);
                t++;
            }
            add(a[i].id);
            while(a[i].value==a[i+1].value && i<=N)
            {
                 i++;
                 add(a[i].id);
            }
            while(que[t].H==a[i].value && que[t].H!=-1)
            {
                ans[ que[t].cnt ]=sum(que[t].R)-sum(que[t].L-1);
                t++;
            }
    }
    for(int i=t;i<=M;i++)
    {
        ans[que[i].cnt]=sum(que[i].R)-sum(que[i].L-1);
    }
}
int main()
{
    // freopen("test.txt","r",stdin);
    int t;
    scanf("%d",&t);
    int Case=1;
    for(int Case=1;Case<=t;Case++)
    {
      scanf("%d%d",&N,&M);
      init();
      for(int i=1;i<=N;i++)
      {
        scanf("%d",&a[i].value);
        a[i].id=i;
      }
      for(int i=1;i<=M;i++)
      {
         scanf("%d%d%d",&que[i].L,&que[i].R,&que[i].H);
         que[i].L++;
         que[i].R++;
         que[i].cnt=i;
      }
      sort(a+1,a+N+1,cmp1);
      sort(que+1,que+M+1,cmp2);
       solve();
       printf("Case %d:
",Case);
        for(int i = 1; i <= M; ++i){
          printf("%d
",ans[i]);
       }
    }

    return 0;
}

边查边插:

#include <iostream>
#include <cstdio>
#include <time.h>
#include <stdlib.h>
#include <cstring>
#include<algorithm>
#define maxn 110000
#define LL  int
using namespace std;
struct node
{
   LL value,id;
};
struct querynode
{
    LL L,R,H,cnt;
};
node a[maxn];
querynode  que[maxn];
LL c[maxn];
LL N,M;
LL ans[maxn];
void init()
{
   memset(a,0,sizeof(a));
   memset(c,0,sizeof(c));
   memset(ans,0,sizeof(ans));
   for(int i=0;i<maxn;i++)
   {
       que[i].H=-1;
   }
}

bool cmp1(node a,node b)
   {
       return a.value<b.value;
   }
bool cmp2(querynode a,querynode b)
{
        return a.H<b.H;
}
int inline lowbit(int x){
    return x & (-x);
}
void inline add(int x){
    while(x <= N ){
       c[x]++;
       x += lowbit(x);
    }
}
int inline sum(int x){
    int s = 0;
    while(x > 0){
      s += c[x];
      x -= lowbit(x);
    }
    return s;
}

void solve1()
{
       for(int aski = 0,ditj = 0; aski < M; ++aski){
           while(ditj < N && que[aski].H >= a[ditj].value){
              add(a[ditj].id);
              ditj++;
           }
           ans[que[aski].cnt] = sum(que[aski].R) - sum(que[aski].L - 1);
       }
}
int main()
{
     //freopen("test.txt","r",stdin);
    int t;
    scanf("%d",&t);
    int Case=1;
    for(int Case=1;Case<=t;Case++)
    {
      scanf("%d%d",&N,&M);
      init();
      for(int i=0;i<N;i++)
      {
        scanf("%d",&a[i].value);
        a[i].id=i+1;
      }
      for(int i=0;i<M;i++)
      {
         scanf("%d%d%d",&que[i].L,&que[i].R,&que[i].H);
         que[i].L++;
         que[i].R++;
         que[i].cnt=i+1;
      }
      sort(a,a+N,cmp1);
      sort(que,que+M,cmp2);
       solve1();
       printf("Case %d:
",Case);
        for(int i = 1; i <= M; ++i){
          printf("%d
",ans[i]);
       }
    }

    return 0;
}
原文地址:https://www.cnblogs.com/xianbin7/p/4786644.html