HDU 4417 Super Mario(区划树+二分)
HDU 4417 Super Mario(划分树+二分)
题目大意:
(L,R,H) L,R之间比H小的数有多少个
借用网上搭牛模板。
我们二分K 。然后用划分树找到第K大的。
看和这个数的关系。
#include<iostream> #include<stdio.h> #include<string.h> #include<cmath> #include<queue> #include<stack> #include<set> #include<map> #include<algorithm> #define ll long long #define eps 1e-5 #define oo 1000000007 #define pi acos(-1.0) #define MAXN 100005 using namespace std; int tree[21][MAXN],Num[21][MAXN],sorted[MAXN]; void build(int s,int e,int t) { if (s==e) return; int i,x,y,mid=s+e>>1,m=mid-s+1; x=s,y=mid+1; for (i=s;i<=e;i++) if (sorted[i]<sorted[mid]) m--; for (i=s;i<=e;i++) { Num[t][i]=Num[t][i-1]; if (tree[t][i]==sorted[mid]) { if (m) tree[t+1][x++]=tree[t][i],Num[t][i]++,m--; else tree[t+1][y++]=tree[t][i]; }else if (tree[t][i]<sorted[mid]) tree[t+1][x++]=tree[t][i],Num[t][i]++; else tree[t+1][y++]=tree[t][i]; } build(s,mid,t+1),build(mid+1,e,t+1); } int query(int t,int s,int e,int l,int r,int k) { if (l==r) return tree[t][l]; int ltoL,LtoR,mid=s+e>>1; ltoL=Num[t][l-1]-Num[t][s-1],LtoR=Num[t][r]-Num[t][l-1]; if (LtoR>=k) return query(t+1,s,mid,s+ltoL,s+ltoL+LtoR-1,k); int b=l-s-ltoL,bb=r-l+1-LtoR; return query(t+1,mid+1,e,mid+b+1,mid+b+bb,k-LtoR); } void init(int n) { for(int i=1;i<=n;i++) { scanf("%d",&tree[0][i]); sorted[i]=tree[0][i]; } memset(Num,0,sizeof(Num)); sort(sorted+1,sorted+1+n); build(1,n,0); } int main() { int n,m; int CASE=1; int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); printf("Case %d:\n",CASE++); init(n); while(m--) { int L,R,H; scanf("%d%d%d",&L,&R,&H); L++,R++; int l=0,r=R-L+2; while(r-l>1) { int mid=(l+r)>>1; if(query(0,1,n,L,R,mid)<=H)l=mid; else r=mid; } printf("%d\n",l); } } return 0; }
- 1楼cc_again昨天 23:22
- 牛叉。加油