今天刚学的主席树,附上博客:主席树
个人觉得这篇文章写的非常好。
主席树就是对于序列 1...n 的每一个前缀都构造一颗线段树来维护所要求的值。也就是说主席树实际上就是 n 棵线段树。那么为什么不会 MLE ?这个下面再说。
时间复杂度: o(nlogn)
空间复杂度: o(nlogn)
下面贴一下这题的代码:(模板题)
#include
using namespace std;
typedef long long LL;
typedef vector <int> VI;
typedef pair <int,int> PII;
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
const int maxn = 100010;
int n,m,a[maxn],b[maxn];
map <int,int> mat;
struct Tree{
int ls,rs,sum;
}tree[maxn*20];
int rt[maxn],tot;
int build(int l,int r){
int o = tot++;
tree[o].sum = 0;
if(l == r) return o;
int mid = (l+r)>>1;
tree[o].ls = build(l,mid);
tree[o].rs = build(mid+1,r);
return o;
}
int update(int x,int l,int r,int lt,int v){
int o = tot++;
tree[o] = tree[lt];
tree[o].sum += v;
if(l == r) return o;
int mid = (l+r)>>1;
if(x <= mid) tree[o].ls = update(x,l,mid,tree[lt].ls,v);
else tree[o].rs = update(x,mid+1,r,tree[lt].rs,v);
return o;
}
int query(int i,int j,int x,int l,int r){
if(l == r) return tree[i].sum - tree[j].sum;
int mid = (l+r)>>1,ret = 0;
if(x <= mid) ret += query(tree[i].ls,tree[j].ls,x,l,mid);
else{
ret += tree[tree[i].ls].sum - tree[tree[j].ls].sum;
ret += query(tree[i].rs,tree[j].rs,x,mid+1,r);
}
return ret;
}
void debug(int o,int l,int r){
if(l == r) {printf("%d:%d ",l,tree[o].sum);return;}
int mid = (l+r) >> 1;
debug(tree[o].ls,l,mid);
debug(tree[o].rs,mid+1,r);
}
int main(){
freopen("test.in","r",stdin);
int T,tCase = 0; scanf("%d",&T);
while(T--){
printf("Case %d:\n",++tCase);
scanf("%d%d",&n,&m);
FOR(i,1,n+1) scanf("%d",&a[i]),b[i] = a[i];
sort(b+1,b+n+1);
int sz = unique(b+1,b+n+1)-b-1;
FOR(i,1,sz+1) mat[b[i]] = i;
tot = 0;
rt[0] = build(1,sz);
FOR(i,1,n+1) rt[i] = update(mat[a[i]],1,sz,rt[i-1],1);
/*
FOR(i,1,n+1){
debug(rt[i],1,sz); printf("\n");
}
*/
FOR(i,0,m){
int l,r,h;
scanf("%d%d%d",&l,&r,&h);
r ++; l ++;
int k = upper_bound(b+1,b+sz+1,h)-b-1;
//printf("r:%d l:%d k:%d ",r,l,k);
if(k) printf("%d\n",query(rt[r],rt[l-1],k,1,sz));
else printf("0\n");
}
}
return 0;
}