Input The first line follows an integer T, the number of test data.
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)
Output For each case, output "Case X: " (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.
Sample Input
1 10 10 0 5 2 7 5 4 3 8 7 7 2 8 6 3 5 0 1 3 1 1 9 4 0 1 0 3 5 5 5 5 1 4 6 3 1 5 7 5 7 3
Sample Output
Case 1: 4 0 0 3 1 2 0 1 5 1
Source 2012 ACM/ICPC Asia Regional Hangzhou Online
思路:求区间内不大于给定数的最大数在该区间的第K大。求第K大可以用划分树,然后就二分一下K就好了。
#include#include using namespace std; int sum[20][100005],node[20][100005],sorted[100005]; void build(int c,int s,int e) { int mid,lp,rp,lm,i; mid=(s+e)>>1; lm=0; lp=s; rp=mid+1; for(i=s;i<=mid;i++) if(sorted[i]==sorted[mid]) lm++; for(i=s;i<=e;i++) { if(s==i) sum[c][i]=0; else sum[c][i]=sum[c][i-1]; if(node[c][i]==sorted[mid]) { if(lm) { lm--; sum[c][i]++; node[c+1][lp++]=node[c][i]; } else node[c+1][rp++]=node[c][i]; } else if(node[c][i] >1; if(rs>=k) return query(c+1,s,mid,s+ls,s+ls+rs-1,k); else return query(c+1,mid+1,e,mid-s+1-ls+l,mid-s+1-ls-rs+r,k-rs); } } int main() { int T,n,m,i,a,b,c,l,r,mid,ans,casenum; scanf("%d",&T); for(casenum=1;casenum<=T;casenum++) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&sorted[i]); node[0][i]=sorted[i]; } sort(sorted+1,sorted+n+1); build(0,1,n); printf("Case %d:\n",casenum); while(m--) { scanf("%d%d%d",&a,&b,&c); if(query(0,1,n,a+1,b+1,1)>c)//特判 { printf("0\n"); continue; } l=1,r=b-a+1; while(l<=r)//二分 { mid=(l+r)>>1; if(query(0,1,n,a+1,b+1,mid)<=c) { ans=mid; l=mid+1; } else { r=mid-1; } } printf("%d\n",ans); } } }