码迷,mamicode.com
首页 > 其他好文 > 详细

HDU - 4417 Super Mario 主席树

时间:2018-06-19 22:43:44      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:#define   数列   \n   i++   题意   个数   sort   col   str   

题意:

  给一个数列$\{ a_i \}$,一些询问$(l_i,r_i,h_i)$,求$j\in [l_i,r_i] ,a_j<=h_i$的元素数量

题解:

  问区间内$<=h$的个数 等于是询问$[l,r]$区间内$[0,upperbound(h)]$的元素个数,就可以

  对于整个区间,很明显是类似权值线段树的逆序对问题,而对于$[l,r]$,利用主席树的可减性进行求解即可

#include <bits/stdc++.h>
#define nd seg[now]
#define ndp seg[pre]
#define mid ((s+t)>>1)
using namespace std;
const int maxn=1e5+10;
int casn,n,m,k;
int num[maxn],rt[maxn],size,pos[maxn];
struct node{
	int l,r,sum;
}seg[maxn*20];
void maketree(int s=1,int t=n,int &now=rt[0]){
	now=++size;nd={s,t,0};
	if(s==t) return ;
	maketree(s,mid,nd.l);maketree(mid+1,t,nd.r);
}
void update(int &now,int pre,int k,int s=1,int t=n){
	now=++size;nd=ndp,nd.sum++;
	if(s==t) return ;
	if(k<=mid)update(nd.l,ndp.l,k,s,mid);
	else update(nd.r,ndp.r,k,mid+1,t);
}
int query(int now,int pre,int l,int r,int s=1,int t=n){
	if(l>t||r<s||l>r) return 0;
	if(l<=s&&r>=t) return ndp.sum-nd.sum;
	return query(nd.l,ndp.l,l,r,s,mid)+query(nd.r,ndp.r,l,r,mid+1,t);
}
int main(){
	scanf("%d",&casn);
	int tt=0;
	while(casn--){
		scanf("%d%d",&k,&m);
		size=0;
		for(int i=1;i<=k;i++){
			scanf("%d",num+i);
			pos[i]=num[i];
		}
		sort(pos+1,pos+1+k);
		n=unique(pos+1,pos+1+k)-pos;
		maketree();
		for(int i=1;i<=k;i++){
			int id=lower_bound(pos+1,pos+1+n,num[i])-pos;
			update(rt[i],rt[i-1],id);
		}
		printf("Case %d:\n",++tt);
		while(m--){
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			a++,b++;
			int k=upper_bound(pos+1,pos+1+n,c)-pos;
			if(pos[k]>c)k--;
			printf("%d\n",query(rt[a-1],rt[b],0,k));
		}
	}
  return 0;
}

  技术分享图片

 

HDU - 4417 Super Mario 主席树

标签:#define   数列   \n   i++   题意   个数   sort   col   str   

原文地址:https://www.cnblogs.com/nervendnig/p/9201161.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!