1. 程式人生 > >換個角度思考

換個角度思考

esc roo div view names cst mat 函數 一個

換個角度思考

https://ac.nowcoder.com/acm/contest/275/E

題目描述

給定一個序列,有多次詢問,每次查詢區間裏小於等於某個數的元素的個數
即對於詢問 (l,r,x),你需要輸出 技術分享圖片 的值
其中 [exp] 是一個函數,它返回 1 當且僅當 exp 成立,其中 exp 表示某個表達式

輸入描述:

第一行兩個整數n,m
第二行n個整數表示序列a的元素,序列下標從1開始標號,保證1 ≤ a
i
 ≤ 10
5

之後有m行,每行三個整數(l,r,k),保證1 ≤ l ≤ r ≤ n,且1 ≤ k ≤ 10
5

輸出描述:

對於每一個詢問,輸出一個整數表示答案後回車
示例1

輸入

5 1
1 2 3 4 5
1 5 3

輸出

3

備註:

數據範圍
1 ≤ n ≤ 10
5

1 ≤ m ≤ 10
5

主席樹模板題

如果是向右子樹走的話,要加上左子樹的值

技術分享圖片
 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\n",query(root[x-1],root[y],k,1,1e5+5)); 65 } 66 }
View Code

換個角度思考