这题一开始像个憨憨一样统计最大值最小值然后直接在线处理
不出意料地t掉了
从zw那里晓得要用离线做
想了好久思维还是停专题的i题的离线思路上
最后发现我的侧重点都是错的
线段树做法
题目思路
把每个位置的高度和每次查询的高度分别从小到大排序
然后从高度小的区间开始查询
每次查询前把比这个高度小的还未放进线段树的值存进树里面
最后统计每次有多少个数存进线段树里面就好
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1000000007;
//998244353
ll t[maxn<<2],tmin[maxn<<2],lz[maxn<<2],ans[maxn];
struct node
{
int l,r,h,in;
}e[maxn];
struct Q
{
int in;
ll h;
}a[maxn];
void pushup(int rt)
{
t[rt]=t[rson]+t[lson];
}
void build(int rt,int l,int r)
{
t[rt]=0;
if(l==r)
{
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
}
ll query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return t[rt];
}
int mid=(l+r)>>1;
ll res=0;
if(L<=mid)
res+=query(lson,l,mid,L,R);
if(R>mid)
res+=query(rson,mid+1,r,L,R);
return res;
}
void modify(int rt,int l,int r,int p)
{
if(l==r)
{
t[rt]=1;
return;
}
int mid=(l+r)>>1;
if(p<=mid)
modify(lson,l,mid,p);
else
modify(rson,mid+1,r,p);
pushup(rt);
}
bool cmp(node a,node b)
{
return a.h<b.h;
}
bool cmp1(Q a,Q b)
{
return a.h<b.h;
}
int main()
{
int _,ce=0;
scanf("%d",&_);
while(_--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i].h);
a[i].in=i;
}
build(1,1,n);
printf("Case %d:\n",++ce);
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&e[i].l,&e[i].r,&e[i].h);
e[i].in=i;
e[i].l++,e[i].r++,e[i].h;
}
sort(e+1,e+1+m,cmp);
sort(a+1,a+1+n,cmp1);
int tem=1;
for(int i=1;i<=m;i++)
{
int le=e[i].l;
int ri=e[i].r;
int h=e[i].h;
while(a[tem].h<=h)
{
modify(1,1,n,a[tem].in);
tem++;
}
ans[e[i].in]=query(1,1,n,le,ri);
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
}
}