放个传送门开溜
题意
给你一串序列,每次询问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;
}
其他
推荐题目,与本题相似