题意:给定一段区间每个点有个高度。在m次询问中每次给出左右端点和可以到达的高度,统计有多少个是小于到达高度
线段树
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define maxn 100001
#define MAXN 100001
int MAX[maxn<<2];
int scan()
{
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-') //判断正负
flag = 1;
else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
}
struct Node
{
int s,t;
int h;
int index;
}node[MAXN];
int answer[MAXN];
struct SS
{
int index;
int v;
}nn[MAXN];
void PushUP(int rt) {
MAX[rt] = MAX[rt<<1] + MAX[rt<<1|1];
}
void build(int l,int r,int rt) {
if (l == r)
{
//scanf("%d",&MAX[rt][0]);
MAX[rt]=0;
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUP(rt);
}
void update(int p,int add,int l,int r,int rt) {
if (l == r) {
MAX[rt] += add;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p , add , lson);
else update(p , add , rson);
PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R)
{
return MAX[rt];
}
int m = (l + r) >> 1;
int ret = 0;
//递归调用每回求最值
if (L <= m) ret += query(L , R , lson);
if (R > m) ret += query(L , R , rson);
return ret;
}
bool cmp(SS a,SS b)
{
return a.v<b.v;
}
bool cmp2(Node a,Node b)
{
return a.h<b.h;
}
int main()
{
int T;
int m;
int n;
int iCase=0;
T=scan();
while(T--)
{
iCase++;
n=scan();
m=scan();
//scanf("%d%d",&n,&m);
build(1,n,1);
for(int i=1;i<=n;i++)
{
nn[i].v=scan();
//scanf("%d",&nn[i].v);
nn[i].index=i;
}
for(int i=0;i<m;i++)
{
node[i].s=scan();
node[i].t=scan();
node[i].h=scan();
//scanf("%d%d%d",&node[i].s,&node[i].t,&node[i].h);
node[i].s++;
node[i].t++;
node[i].index=i;
}
sort(node,node+m,cmp2);
sort(nn+1,nn+1+n,cmp);
int i,j;
i=1;
j=0;
while(j<m)
{
while(i<=n)
{
if(nn[i].v>node[j].h)break;
update(nn[i].index,1,1,n,1);
i++;
}
while(j<m)
{
if(i<=n&&node[j].h>=nn[i].v)break;
answer[node[j].index]=query(node[j].s,node[j].t,1,n,1);
j++;
}
}
printf("Case %d:\n",iCase);
for(int i=0;i<m;i++)
printf("%d\n",answer[i]);
}
return 0;
}
树状数组
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int MAXN=100010;
int c[MAXN];
int n;
int lowbit(int x)
{
return x&(-x);
}
void plus(int i,int val)
{
while(i<=n)
{
c[i]+=val;
i+=lowbit(i);
}
}
int sum(int i)
{
int s=0;
while(i>0)
{
s+=c[i];
i-=lowbit(i);
}
return s;
}
struct Node
{
int s,t;
int h;
int index;
}node[MAXN];
int answer[MAXN];
struct SS
{
int index;
int v;
}nn[MAXN];
bool cmp(SS a,SS b)
{
return a.v<b.v;
}
bool cmp2(Node a,Node b)
{
return a.h<b.h;
}
int input()
{
int ret=0;
char ch;
ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')
{
ret*=10;
ret+=ch-'0';
ch=getchar();
}
return ret;
}
int main()
{
int T;
int m;
int iCase=0;
scanf("%d",&T);
//T=input();
while(T--)
{
iCase++;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&nn[i].v);
//nn[i].v=input();
nn[i].index=i;
}
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&node[i].s,&node[i].t,&node[i].h);
//node[i].s=input();
//node[i].t=input();
//node[i].h=input();
node[i].s++;
node[i].t++;
node[i].index=i;
//从1开始 所以全部起点终点++
}
memset(c,0,sizeof(c));
sort(node,node+m,cmp2);
sort(nn+1,nn+1+n,cmp);
int i,j;
i=1;
j=0;
while(j<m)
{
//因为已经排序所以可以直接统计
while(i<=n)
{
if(nn[i].v>node[j].h)break;
plus(nn[i].index,1);
i++;
}
while(j<m)
{
if(i<=n&&node[j].h>=nn[i].v)break;
answer[node[j].index]=sum(node[j].t)-sum(node[j].s-1);
j++;
/*因为前一次询问(while(i<=n))已经找到满足当前询问满足的最大高度位置为i
下一次询问的H比当前节点的i的值要还要高说明需要找节点i(当前满足条件节点)
之后是否有满足条件的,这样省去了标记每个节点是否需要访问 */
}
}
printf("Case %d:\n",iCase);
for(int i=0;i<m;i++)
printf("%d\n",answer[i]);
}
return 0;
}