查詢區間裡有多少個小於k的數
阿新 • • 發佈:2020-08-20
用主席樹可以線上做,樹狀陣列只能離線。
先放個主席樹的。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<queue> 5 #include<set> 6 #include<string> 7 #include<cmath> 8 #include<cstring> 9 #define FF first 10 #define SS second 11 #define ll long long 12#define pb push_back 13 #define pm make_pair 14 using namespace std; 15 typedef pair<int,int> PII; 16 const int MAX = 1e5 + 5; 17 struct TREE { 18 int l,r; 19 int val; 20 } tr[MAX*40]; 21 22 int tot; 23 int a[MAX],b[MAX]; 24 int root[MAX]; 25 int build(int l,int r) { 26 int cur = ++tot;27 tr[cur].val = 0; 28 if(l == r) { 29 tr[cur].l = tr[cur].r = 0;//這一步好像沒啥用? 30 return cur; 31 } 32 int m = (l+r)>>1; 33 tr[cur].l = build(l,m); 34 tr[cur].r = build(m+1,r); 35 return cur; 36 } 37 void pushup(int cur) { 38 tr[cur].val = tr[tr[cur].l].val + tr[tr[cur].r].val;39 } 40 int update(int pre,int tar,int l,int r) { 41 int cur = ++tot; 42 tr[cur] = tr[pre]; 43 if(l == r) { 44 tr[cur].val++; 45 return cur; 46 } 47 int m = (l+r)>>1; 48 if(tar <= m) tr[cur].l = update(tr[pre].l,tar,l,m); 49 else tr[cur].r = update(tr[pre].r,tar,m+1,r); 50 pushup(cur); 51 return cur; 52 } 53 int query(int pl,int pr,int l,int r,int H) { 54 if(l == r) return tr[pr].val - tr[pl].val; 55 int m = (l+r)>>1; 56 if(H <= m) return query(tr[pl].l,tr[pr].l,l,m,H); 57 else return tr[tr[pr].l].val - tr[tr[pl].l].val + query(tr[pl].r,tr[pr].r,m+1,r,H); 58 } 59 int main() 60 { 61 int n,m; 62 int t,iCase=0; 63 cin>>t; 64 while(t--) { 65 printf("Case %d:\n",++iCase); 66 cin>>n>>m; 67 tot=0; 68 for(int i = 1; i<=n; i++) scanf("%d",a+i),b[i] = a[i]; 69 root[0] = build(1,n); 70 sort(b+1,b+n+1); 71 int LEN = unique(b+1,b+n+1) - b - 1; 72 for(int i = 1; i<=n; i++) { 73 int pos = lower_bound(b+1,b+LEN+1,a[i]) - b; 74 root[i] = update(root[i-1],pos,1,n); 75 } 76 while(m--) { 77 int l,r,H; 78 scanf("%d%d%d",&l,&r,&H);l++,r++; 79 int pos = upper_bound(b+1,b+LEN+1,H) - b - 1; 80 if(pos) printf("%d\n",query(root[l-1],root[r],1,n,pos)); 81 else printf("0\n"); 82 } 83 } 84 return 0 ; 85 }
再放一個樹狀陣列的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int maxm=1e5+5; 8 struct Data{ 9 int num,id; 10 bool operator<(const Data a){//按數值大小排序 11 return num<a.num; 12 } 13 }a[maxm]; 14 struct Query{ 15 int l,r,h,id; 16 bool operator<(const Query a){//按h排序 17 return h<a.h; 18 } 19 }q[maxm]; 20 int c[maxm];//BIT 21 int res[maxm];//存答案 22 int n,m; 23 int cas=1; 24 void init(){ 25 memset(c,0,sizeof c); 26 } 27 int lowbit(int i){ 28 return i&-i; 29 } 30 void add(int i,int x){ 31 while(i<=n){ 32 c[i]+=x; 33 i+=lowbit(i); 34 } 35 } 36 int ask(int i){ 37 int ans=0; 38 while(i){ 39 ans+=c[i]; 40 i-=lowbit(i); 41 } 42 return ans; 43 } 44 void input(){ 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=n;i++){ 47 scanf("%d",&a[i].num); 48 a[i].id=i; 49 } 50 for(int i=1;i<=m;i++){ 51 scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h); 52 q[i].l++,q[i].r++;//題目區間從0開始,加1變為從1開始 53 q[i].id=i; 54 } 55 sort(a+1,a+1+n); 56 sort(q+1,q+1+m); 57 } 58 void solve(){ 59 printf("Case %d:\n",cas++); 60 int last=1; 61 for(int i=1;i<=m;i++){ 62 while(q[i].h>=a[last].num&&last<=n){//把數值比h小的插入 63 add(a[last].id,1);//插入的是編號 64 last++; 65 } 66 res[q[i].id]=ask(q[i].r)-ask(q[i].l-1); 67 } 68 for(int i=1;i<=m;i++){ 69 printf("%d\n",res[i]); 70 } 71 } 72 int main(){ 73 int T; 74 scanf("%d",&T); 75 while(T--){ 76 init(); 77 input(); 78 solve(); 79 } 80 return 0; 81 }
HDU 4417,板題。