换个角度思考
https://ac.nowcoder.com/acm/contest/275/E
题目描述
给定一个序列,有多次询问,每次查询区间里小于等于某个数的元素的个数
即对于询问 (l,r,x),你需要输出 的值
其中 [exp] 是一个函数,它返回 1 当且仅当 exp 成立,其中 exp 表示某个表达式
即对于询问 (l,r,x),你需要输出 的值
其中 [exp] 是一个函数,它返回 1 当且仅当 exp 成立,其中 exp 表示某个表达式
输入描述:
第一行两个整数n,mi
第二行n个整数表示序列a的元素,序列下标从1开始标号,保证1 ≤ a
≤ 105
5
之后有m行,每行三个整数(l,r,k),保证1 ≤ l ≤ r ≤ n,且1 ≤ k ≤ 10
输出描述:
对于每一个询问,输出一个整数表示答案后回车
示例1
输入
5 1 1 2 3 4 5 1 5 3
输出
3
备注:
数据范围5
1 ≤ n ≤ 10
5
1 ≤ m ≤ 10
主席树模板题
如果是向右子树走的话,要加上左子树的值
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #include<set> 5 #include<map> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #include<cstdio> 10 #define N 500005 11 using namespace std; 12 struct sair{ 13 int l,r,v; 14 }tree[N*40]; 15 int root[N],cnt; 16 17 void pushup(int rt){ 18 tree[rt].v=tree[tree[rt].l].v+tree[tree[rt].r].v; 19 } 20 21 void add(int pre,int cur,int pos,int l,int r){ 22 if(l==r){ 23 tree[cur].v=tree[pre].v+1; 24 return; 25 } 26 int mid=(l+r)/2; 27 if(pos<=mid){ 28 tree[cur].l=++cnt; 29 tree[cur].r=tree[pre].r; 30 add(tree[pre].l,tree[cur].l,pos,l,mid); 31 } 32 else{ 33 tree[cur].r=++cnt; 34 tree[cur].l=tree[pre].l; 35 add(tree[pre].r,tree[cur].r,pos,mid+1,r); 36 } 37 pushup(cur); 38 } 39 40 int query(int pre,int cur,int k,int l,int r){ 41 if(l==r){ 42 return tree[cur].v-tree[pre].v; 43 } 44 int mid=(l+r)/2; 45 int ans=0; 46 if(k<=mid) 47 ans+=query(tree[pre].l,tree[cur].l,k,l,mid); 48 else 49 ans+=tree[tree[cur].l].v-tree[tree[pre].l].v+query(tree[pre].r,tree[cur].r,k,mid+1,r); 50 return ans; 51 } 52 53 int main(){ 54 int n,m,x,y,k; 55 scanf("%d %d",&n,&m); 56 cnt=0; 57 for(int i=1;i<=n;i++){ 58 scanf("%d",&x); 59 root[i]=++cnt; 60 add(root[i-1],root[i],x,1,1e5+5); 61 } 62 while(m--){ 63 scanf("%d %d %d",&x,&y,&k); 64 printf("%d ",query(root[x-1],root[y],k,1,1e5+5)); 65 } 66 }