题意:给你n个数,m个查询,对于每个查询,问在区间[a,b]内找到一个数x,使得最小。
同样是划分树,只是多记录了一个sum域,表示进入左子树的数的和。
如果不懂划分树:http://blog.csdn.net/shiqi_614/article/details/8041390
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define MID(a,b) (a+((b-a)>>1)) typedef long long LL; const int N=1e5+5; struct P_Tree { int order[N],n; int toLft[20][N],valu[20][N]; LL sum[N],lsum[20][N],isum; void init(int len) { n=len; sum[0]=0; for(int i=0;i<20;i++) lsum[i][0]=0,toLft[i][0]=0; for(int i=1;i<=n;i++) { scanf("%d",&order[i]); valu[0][i]=order[i]; sum[i]=sum[i-1]+order[i]; } sort(order+1,order+1+n); build(1,n,0); } void build(int lft,int rht,int ind) { if(lft==rht) return; int mid=MID(lft,rht); int same=mid-lft+1,ln=lft,rn=mid+1; for(int i=lft;i<=rht;i++) if(valu[ind][i]<order[mid]) same--; for(int i=lft;i<=rht;i++) { int flag=0; if((valu[ind][i]<order[mid])||valu[ind][i]==order[mid]&&same>0) { flag=1; valu[ind+1][ln++]=valu[ind][i]; if(valu[ind][i]==order[mid]) same--; lsum[ind][i]=lsum[ind][i-1]+valu[ind][i]; } else { lsum[ind][i]=lsum[ind][i-1]; valu[ind+1][rn++]=valu[ind][i]; } toLft[ind][i]=toLft[ind][i-1]+flag; } build(lft,mid,ind+1); build(mid+1,rht,ind+1); } int query(int st,int ed,int k,int lft,int rht,int ind) { if(lft==rht) return valu[ind][lft]; int mid=MID(lft,rht); int lx=toLft[ind][st-1]-toLft[ind][lft-1]; int ly=toLft[ind][ed]-toLft[ind][st-1]; int rx=st-1-lft+1-lx; int ry=ed-st+1-ly; if(ly>=k) return query(lft+lx,lft+lx+ly-1,k,lft,mid,ind+1); else { isum+=lsum[ind][ed]-lsum[ind][st-1]; st=mid+1+rx; ed=mid+1+rx+ry-1; return query(st,ed,k-ly,mid+1,rht,ind+1); } } LL solve(int a,int b,int k) { LL ele=query(a,b,k,1,n,0); LL res1=sum[b]-sum[a-1]-isum-ele-(b-a+1-k)*ele; LL res2=ele*(k-1)-isum; return res1+res2; } }tree; int main() { int t,t_cnt=0; scanf("%d",&t); while(t--) { int n,m,a,b,k; scanf("%d",&n); tree.init(n); scanf("%d",&m); printf("Case #%d:\n",++t_cnt); while(m--) { tree.isum=0; scanf("%d%d",&a,&b); a++;b++; k=(b-a+2)/2; LL res=tree.solve(a,b,k); printf("%I64d\n",res); } puts(""); } return 0; }