HDU - 4417 Super Mario

放个传送门开溜

题意

给你一串序列,每次询问L~R范围内小于等于H数字的个数

题解

由于今天我们学的分块,所以被逼用分块

关于分块,蒟蒻不再赘述,推荐一篇讲分块的blog

还是运用分块的思想,小于bol(bol为每块的长度)的首尾,暴力求ans

中间排好序用STL中的upper_bound统计小于等于H的

完了

注意

卡常是要卡滴,o2是要开的

注意好像原序列从0开始排,所以如果习惯for(int i=1;i<=n;++i),记得L++,R++

CODE

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
#pragma GCC optimize (2)
#pragma G++ optimize (2)
#define N 100005
#define rint register int
using namespace std;
int t,n,m,bol,v[N],bel[N];
vector<int> xl[400];
inline int read()
{
    rint x=0,f=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void write(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
inline int query(int a,int b,int h)
{
    rint ans=0;
    for(rint i=a;i<=min(bel[a]*bol,b);++i) if(v[i]<=h) ++ans;
    if(bel[a]!=bel[b]) for(rint i=(bel[b]-1)*bol+1;i<=b;++i)  if(v[i]<=h) ++ans;
    for(rint i=bel[a]+1;i<bel[b];++i) 
    {
        if(h<*xl[i].begin()) continue;
        ans+=upper_bound(xl[i].begin(),xl[i].end(),h)-xl[i].begin();
     }
    return ans;
}
int main()
{
    //freopen("2.out","w",stdout);
    t=read();
    for(rint qwq=1;qwq<=t;++qwq)
    {
        rint a,b,h;
        n=read();m=read();bol=sqrt(n);
        for(rint i=1;i<=n;++i) v[i]=read(),bel[i]=(i-1)/bol+1,xl[bel[i]].push_back(v[i]);
        for(rint i=1;i<=bel[n];++i) sort(xl[i].begin(),xl[i].end());
        if(qwq!=1) putchar('\n');
        putchar('C');putchar('a');putchar('s');putchar('e');putchar(' ');write(qwq);putchar(':');
        for(rint i=1;i<=m;++i)
        {
            a=read();b=read();h=read();a++;b++;
            putchar('\n');write(query(a,b,h));
        }
        if(qwq!=t) for(rint i=1;i<=n;++i) xl[i].clear();
        if(qwq==t) putchar('\n');
    }
    return 0;
}

 

其他

推荐题目,与本题相似

posted @ 2019-08-21 20:34  sooner  阅读(7)  评论(0编辑  收藏  举报