标签:des style blog http os 2014
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
Case 1: 4 0 0 3 1 2 0 1 5 1
思路:求区间内不大于给定数的最大数在该区间的第K大。求第K大可以用划分树,然后就二分一下K就好了。
#include <cstdio> #include <algorithm> 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]<sorted[mid]) { sum[c][i]++; node[c+1][lp++]=node[c][i]; } else node[c+1][rp++]=node[c][i]; } if(s!=e) { build(c+1,s,mid); build(c+1,mid+1,e); } } int query(int c,int s,int e,int l,int r,int k) { if(s==e) return node[c][s]; else { int ls,rs,mid; if(s==l) { ls=0; rs=sum[c][r]; } else { ls=sum[c][l-1]; rs=sum[c][r]-ls; } mid=(s+e)>>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); } } }
HDU-4417-Super Mario(划分树+二分),布布扣,bubuko.com
标签:des style blog http os 2014
原文地址:http://blog.csdn.net/faithdmc/article/details/37668709