题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417
题意:
给定一个序列,
每次询问[l,r]区间内<=x的元素的个数
算法:
本题解法非常多。
以后我会慢慢补全这篇文章,
当做一次基础数据结构训练。
划分树 (218ms)
#include<cstdio> #include<iostream> #include<sstream> #include<cstdlib> #include<cstring> #include<string> #include<climits> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define eps 1e-8 using namespace std; const int MAXN=110000; int tr[MAXN<<2]; int sorted[MAXN],toleft[20][MAXN],val[20][MAXN]; void build(int l, int r, int dep, int rt) { if(l==r) { return; } int mid=(l+r)>>1; int lnum=mid-l+1; for(int i=l; i<=r; i++) { if(val[dep][i]<sorted[mid]) { lnum--; } } int lp=l,rp=mid+1; int cur_lnum=0; for(int i=l; i<=r; i++) { if(i==l) { toleft[dep][i]=0; } else { toleft[dep][i]=toleft[dep][i-1]; } if(val[dep][i]<sorted[mid]) { toleft[dep][i]++; val[dep+1][lp++]=val[dep][i]; } else if(val[dep][i]>sorted[mid]) { val[dep+1][rp++]=val[dep][i]; } else { if(cur_lnum<lnum) { cur_lnum++; toleft[dep][i]++; val[dep+1][lp++]=val[dep][i]; } else { val[dep+1][rp++]=val[dep][i]; } } } build(l,mid,dep+1,rt<<1); build(mid+1,r,dep+1,rt<<1|1); } int query(int l, int r, int L, int R, int x, int dep, int rt) { if(l==r) { return val[dep][l]<=x; } int lnum,cur_lnum,rnum,cur_rnum; int mid=(l+r)>>1; if(l==L) { lnum=toleft[dep][R]; cur_lnum=0; } else { lnum=toleft[dep][R]-toleft[dep][L-1]; cur_lnum=toleft[dep][L-1]; } if(sorted[mid]>x) { if(!lnum) { return 0; } int newL=l+cur_lnum; int newR=l+lnum+cur_lnum-1; return query(l,mid,newL,newR,x,dep+1,rt<<1); } else { int rnum=R-L+1-lnum; int cur_rnum=L-l-cur_lnum; if(!rnum) { return lnum; } int newL=mid+cur_rnum+1; int newR=mid+cur_rnum+rnum; return lnum+query(mid+1,r,newL,newR,x,dep+1,rt<<1|1); } } int main() { int cas; scanf("%d",&cas); for(int T=1; T<=cas; T++) { int n,m; scanf("%d%d",&n,&m); for(int i=0; i<n; i++) { scanf("%d",&val[0][i]); sorted[i]=val[0][i]; } sort(sorted,sorted+n); build(0,n-1,0,1); printf("Case %d:\n",T); while(m--) { int l,r,x; scanf("%d%d%d",&l,&r,&x); printf("%d\n",query(0,n-1,l,r,x,0,1)); } } return 0; }
#include<cstdio> #include<iostream> #include<sstream> #include<cstdlib> #include<cstring> #include<string> #include<climits> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define eps 1e-8 using namespace std; const int MAXN=110000; int tr[MAXN<<2]; int sorted[MAXN],toleft[20][MAXN],val[20][MAXN]; void build(int l, int r, int dep, int rt) { if(l==r) { return; } int mid=(l+r)>>1; int lnum=mid-l+1; for(int i=l; i<=r; i++) { if(val[dep][i]<sorted[mid]) { lnum--; } } int lp=l,rp=mid+1; int cur_lnum=0; for(int i=l; i<=r; i++) { if(i==l) { toleft[dep][i]=0; } else { toleft[dep][i]=toleft[dep][i-1]; } if(val[dep][i]<sorted[mid]) { toleft[dep][i]++; val[dep+1][lp++]=val[dep][i]; } else if(val[dep][i]>sorted[mid]) { val[dep+1][rp++]=val[dep][i]; } else { if(cur_lnum<lnum) { cur_lnum++; toleft[dep][i]++; val[dep+1][lp++]=val[dep][i]; } else { val[dep+1][rp++]=val[dep][i]; } } } build(l,mid,dep+1,rt<<1); build(mid+1,r,dep+1,rt<<1|1); } int query(int l, int r, int L, int R, int k, int dep, int rt) { if(l==r) { return val[dep][l]; } int lnum,cur_lnum,rnum,cur_rnum; int mid=(l+r)>>1; if(l==L) { lnum=toleft[dep][R]; cur_lnum=0; } else { lnum=toleft[dep][R]-toleft[dep][L-1]; cur_lnum=toleft[dep][L-1]; } if(lnum>=k) { int newL=l+cur_lnum; int newR=l+lnum+cur_lnum-1; return query(l,mid,newL,newR,k,dep+1,rt<<1); } else { int rnum=R-L+1-lnum; int cur_rnum=L-l-cur_lnum; int newL=mid+cur_rnum+1; int newR=mid+cur_rnum+rnum; return query(mid+1,r,newL,newR,k-lnum,dep+1,rt<<1|1); } } int main() { int cas; scanf("%d",&cas); for(int T=1; T<=cas; T++) { int n,m; scanf("%d%d",&n,&m); for(int i=0; i<n; i++) { scanf("%d",&val[0][i]); sorted[i]=val[0][i]; } sort(sorted,sorted+n); build(0,n-1,0,1); printf("Case %d:\n",T); while(m--) { int x,llim,rlim; scanf("%d%d%d",&llim,&rlim,&x); int l=0,r=rlim-llim+1; while(l<r) { int mid=(l+r+1)>>1; if(query(0,n-1,llim,rlim,mid,0,1)<=x) { l=mid; } else { r=mid-1; } } printf("%d\n",l); } } return 0; }
主席树(125ms)
#include<cstdio> #include<iostream> #include<algorithm> #include<sstream> #include<cstdlib> #include<cstring> #include<string> #include<climits> #include<cmath> #include<queue> #include<vector> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define eps 1e-8 using namespace std; const int MAXN = 110000; const int MAXM = 2100000; int tot; typedef struct { int cot, right, left; } NODE; int root[MAXN],a[MAXN]; vector<int> hash; NODE node[MAXM]; int newnode(int cot, int left, int right) { node[tot].cot = cot; node[tot].left = left; node[tot].right = right; return tot ++; } int insert(int rt, int l, int r, int k) { if(l <= k && k <=r) { if(l == r) { return newnode(node[rt].cot + 1, 0, 0); } int mid = (l + r) >> 1; return newnode(node[rt].cot + 1, insert(node[rt].left, l, mid, k), insert(node[rt].right, mid + 1, r, k)); } return rt; } int query(int p, int q, int l, int r, int k) { if(hash[r] <= k) { return node[q].cot - node[p].cot; } if(l == r) { return 0; } int mid = (l + r) >> 1; int ret = query(node[p].left, node[q].left, l, mid, k); if(k >= hash[mid+1]) { ret += query(node[p].right, node[q].right, mid + 1, r, k); } return ret; } int main() { int cas; scanf("%d", &cas); for(int T = 1; T <= cas; T ++) { int n, q; scanf("%d %d", &n, &q); tot=0; root[0]=newnode(0, 0, 0); hash.clear(); for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); hash.push_back(a[i]); } sort(hash.begin(), hash.end()); hash.erase(unique(hash.begin(), hash.end()), hash.end()); int m = hash.size(); for(int i = 1; i <= n; i ++) { a[i] = lower_bound(hash.begin(), hash.end(), a[i]) - hash.begin(); root[i] = insert(root[i - 1], 0, m - 1, a[i]); } printf("Case %d:\n",T); while(q --) { int l, r, k; scanf("%d %d %d",&l, &r, &k); printf("%d\n", query(root[l], root[r + 1], 0, m - 1, k)); } } return 0; }