HDU 4417 Super Mario

题意:给你一个N大小的数列a[0].....a[n-1],输入L,R,H  求[L,R]区间内满足a[i]<=h的数的个数

这里我用了主席树来写

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100005;
const int M = N * 40;
int n,m,q,tot;
int a[N],t[N];
int T[N],ls[M],rs[M],c[M];
void Init_hash(){
	sort(t+1,t+n+1);
	m = unique(t+1,t+1+n)-t-1;
}
int hasha(int x){
	return lower_bound(t+1,t+1+m,x)-t;
}
void build(int l, int r, int &rt){
	rt = tot ++;
	c[rt] = 0;
	if(l != r){
		int mid = (l+r)>>1;
		build(l, mid, ls[rt] );
		build(mid+1, r, rs[rt]);
	}
}
int update(int root, int pos, int val){
	int newroot = tot++, tmp = newroot;
	c[newroot] = c[root] + val;
	int l = 1, r = m;
	while(l < r){
		int mid = (l+r)>>1;
		if(pos <= mid){
			ls[newroot] = tot++;
			rs[newroot] = rs[root];
			newroot = ls[newroot];
			root = ls[root];
			r = mid;
		}
		else {
			rs[newroot] = tot++;
			ls[newroot] = ls[root];
			newroot = rs[newroot];
			root = rs[root];
			l = mid+1;
		}
		c[newroot] = c[root] + val;
	}
	return tmp;
}
int query(int l_root, int r_root, int l, int r, int h){
	if(t[r]<=h){
		return c[r_root] - c[l_root];
	}
	int mid = (l+r)>>1, ans = 0;
	if(t[l] <= h)ans+=query(ls[l_root],ls[r_root],l,mid,h);
	if(t[mid+1] <= h)ans+=query(rs[l_root], rs[r_root], mid+1, r, h);
	return ans;
}
int main(){
	int l,r,h,ks,nn;
	//freopen("in.txt","r",stdin);
	scanf("%d",&nn);
	for(int ks = 1; ks <= nn; ks++){
		printf("Case %d:\n",ks);
		scanf("%d%d",&n, &q);
		tot = m = 0;
		for(int i = 1; i <= n; i++ ){
			scanf("%d", a+i);
			t[i] = a[i];
		}
		Init_hash();
		build(1,m,T[0]);
		for(int i = 1; i <= n; i++){
			T[i] = update(T[i-1], hasha(a[i]), 1);
		}
		for(int i = 0; i < q; i++){
			scanf("%d%d%d", &l, &r, &h);
			printf("%d\n",query(T[l],T[r+1],1,m,h));
		}
	}
	return 0;
}


你可能感兴趣的:(HDU,主席树)