Problem DescriptionYou are given N positive integers, denoted as x0, x1... xN-1. then give you some intervals [l, r]. for each interval, you need to find a number x to make as small as possible!
InputThe first line is an integer T (T <= 10), indicating the number of test cases. for each test case, an integer N (1 <= N <= 100,000) comes first. then comes N positive integers x (1 <= x <= 1,000,000,000) in the next line. finally, comes an integer Q (1 <= Q <= 100,000), indicting there are Q queries. each query consists of two integers l, r (0 <= l <= r <N), meaning the interval you shoshould deal.
OutputFor the k-th test case, first output "Case # k:" in a separate line. then output Q lines, each line is the minimum value. output a blank line after every test case.
Sample Input
253 6 2 2 421 40 227 720 11 1
Sample Output
Case #1:64Case #2:00
Authorstandy
Source2010ACM-ICPC Multi-University Training Contest (4) -- Host by UESTC
Recommendzhengfeng | We have carefully selected several similar problems for you: 3474 1828 3397 3333
It's been a long time since the output of hangdian .... Printf lld, WA requires I64d ..... Really awesome !!!!
It is easy to make the absolute value and minimum value mean the median. You can refer to the principle that the sum of distance between two points on the coordinate is the smallest...
This question gave me a deeper understanding of the principles of the tree.
#include
#include
#include
#include
#include
#include #include
using namespace std;#define md(x, y) (((x)+(y))>>1)const int maxn = 100000+10;typedef long long LL;int n,m;int ls;int num[maxn];int seg[20][maxn];int lftnum[20][maxn];LL lfts[20][maxn];LL presum[maxn];LL lsum;void build(int L,int R,int dep){ if(L==R)return; int mid = md(L,R); int key = num[mid]; int lcnt = mid-L+1; for(int i = L; i <= R; i++){ if(seg[dep][i] < key) lcnt--; } int lp = L,rp = mid+1; for(int i = L; i <= R; i++){ if(i==L){ lftnum[dep][i] = 0; lfts[dep][i] = 0; }else{ lfts[dep][i] = lfts[dep][i-1]; lftnum[dep][i] = lftnum[dep][i-1]; } if(seg[dep][i] < key){ lftnum[dep][i]++; lfts[dep][i] += seg[dep][i]; seg[dep+1][lp++] = seg[dep][i]; } else if(seg[dep][i] > key){ seg[dep+1][rp++] = seg[dep][i]; } else{ if(lcnt>0){ lcnt--; lftnum[dep][i]++; lfts[dep][i] += seg[dep][i]; seg[dep+1][lp++] = seg[dep][i]; }else{ seg[dep+1][rp++] = seg[dep][i]; } } } build(L,mid,dep+1); build(mid+1,R,dep+1);}LL query(int L,int R,int ll,int rr,int dep,int k){ if(ll == rr) return seg[dep][ll]; int mid = md(ll,rr); int ncnt,ucnt; LL tsum = 0; if(L==ll){ ncnt = 0; tsum = lfts[dep][R]; ucnt = lftnum[dep][R]-ncnt; }else{ ncnt = lftnum[dep][L-1]; ucnt = lftnum[dep][R]-ncnt; tsum = lfts[dep][R]-lfts[dep][L-1]; } if(ucnt >= k){ L = ll + ncnt; R = ll + ncnt + ucnt-1; return query(L,R,ll,mid,dep+1,k); }else{ int aa = L-ll-ncnt; int bb = R-L-ucnt+1; L = mid+aa+1; R = mid+aa+bb; ls += ucnt; lsum += tsum; return query(L,R,mid+1,rr,dep+1,k-ucnt); }}int main(){ int ncase,T=1; cin >>ncase; while(ncase--){ scanf("%d",&n); presum[0] = 0; for(int i = 1; i <= n; i++){ scanf("%d",&num[i]); seg[0][i] = num[i]; presum[i] = presum[i-1]+num[i]; } sort(num+1,num+n+1); build(1,n,0); scanf("%d",&m); printf("Case #%d:\n",T++); while(m--){ int a,b,k; scanf("%d%d",&a,&b); ++a;++b; k = (b-a)/2+1; lsum = 0; ls = 0; int rs = 0; int t = query(a,b,1,n,0,k); LL rsum = presum[b]-presum[a-1]-t-lsum; rs = b-a-ls; LL ans = rsum-lsum+t*(ls-rs); printf("%I64d\n",ans); } printf("\n"); } return 0;}