#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 1000000001 #define MOD 1000000007 #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pi acos(-1.0) using namespace std; const int MAXN = 100010; int num[20][MAXN],cnt[20][MAXN],sor[MAXN],n,leftnum; ll sum[20][MAXN],leftsum,all[MAXN];//sum记录第d层 第i个数之前小于sor[m]的和 void build(int l,int r,int d) { if(l == r){ return ; } int m = (l + r) >> 1; int same_m = m - l + 1; for(int i = l; i <= r; i++){ if(num[d][i] < sor[m])same_m --; } int cnt_small = 0; int pl,pr; ll val = 0; pl = l,pr = m + 1; for(int i = l; i <= r; i++){ if(num[d][i] < sor[m]){ cnt_small ++; val += num[d][i]; sum[d][i] = val; cnt[d][i] = cnt_small; num[d+1][pl++] = num[d][i]; } else if(num[d][i] == sor[m] && same_m){ same_m --; cnt_small ++; val += num[d][i]; sum[d][i] = val; cnt[d][i] = cnt_small; num[d+1][pl++] = num[d][i]; } else { sum[d][i] = val; cnt[d][i] = cnt_small; num[d+1][pr++] = num[d][i]; } } build(l,m,d+1); build(m+1,r,d+1); } ll query(int L,int R,int k,int l,int r,int d) { if(l == r){ return num[d][l]; } int m = (l + r) >> 1; int s,ss; ll val = 0; if(l == L)s = 0, val = sum[d][R]; else s = cnt[d][L-1], val = sum[d][R] - sum[d][L-1]; ss = cnt[d][R] - s; if(ss >= k){ int newl = l + s; int newr = l + s + ss - 1; return query(newl,newr,k,l,m,d+1); } else { leftnum += ss;//进入左孩子不用处理,进入右孩子时 就要加上左孩子的值 leftsum += val; int a = L - l - s; int b = R - L + 1 - ss; int newl = m + 1 + a; int newr = m + 1 + a + b - 1; return query(newl,newr,k - ss,m+1,r,d+1); } } int main() { int t,ff = 0; scanf("%d",&t); while(t--){ scanf("%d",&n); memset(all,0,sizeof(all)); memset(num,0,sizeof(num)); for(int i = 1; i <= n; i++){ scanf("%d",&num[1][i]); sor[i] = num[1][i]; all[i] = all[i-1] + sor[i]; } sort(sor + 1,sor + n + 1); build(1,n,1); int q,x,y; scanf("%d",&q); printf("Case #%d:\n",++ff); while(q--){ scanf("%d%d",&x,&y); x += 1; y += 1; int len = (y - x + 1); ll tp; leftnum = 0; leftsum = 0; if(len % 2){ int k = (len + 1) >> 1; tp = query(x,y,k,1,n,1); } else { int k = len >> 1; tp = query(x,y,k,1,n,1); } //cout<<tp<<‘ ‘<<leftnum<<‘ ‘<<leftsum<<‘ ‘<<all[y]<<‘ ‘<<all[x+leftnum]<<endl; ll ans = tp * (leftnum + 1) - (leftsum + tp) + (all[y] - all[x - 1] - (leftsum + tp)) - (y - x + 1 - (leftnum + 1)) * tp; printf("%lld\n",ans); } printf("\n"); } return 0; }
原文:http://www.cnblogs.com/sweat123/p/5543795.html