Description
You 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!
![](https://i-blog.csdnimg.cn/blog_migrate/1790a254ea5f2a7419cb2d995e367b1b.jpeg)
Input
The 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 should deal with.
Output
For the k-th test case, first output “Case #k:” in a separate line. Then output Q lines, each line is the minimum value of
. Output a blank line after every test case.
![](https://i-blog.csdnimg.cn/blog_migrate/1790a254ea5f2a7419cb2d995e367b1b.jpeg)
Sample Input
2 5 3 6 2 2 4 2 1 4 0 2 2 7 7 2 0 1 1 1
Sample Output
Case #1: 6 4 Case #2: 0 0
#include <iostream>
#include <algorithm>
#include <string.h>
#define MAXN 100001
using namespace std;
class Node
{
public:
int l, r;
};
class SGtree
{
public:
Node node[MAXN << 2];
int num_left[20][MAXN];
int sg_node[20][MAXN];
long long sum[18][MAXN];
int parray[MAXN];
void init();
void Maketree(int i, int d, int l, int r);
int Query(int i, int d, int x, int y, int k);
}tree;
void SGtree::init()
{
memset(num_left, 0, sizeof(0));
memset(sg_node, 0, sizeof(sg_node));
memset(node, 0, sizeof(node));
memset(sum, 0, sizeof(sum));
}
void SGtree::Maketree(int o, int d, int l, int r)
{
node[o].l = l;
node[o].r = r;
if (l == r)
{
return ;
}
int mid = (l + r) >> 1;
int issame = mid - l + 1;
for (int i = l; i <= r; i++)
{
if (sg_node[d][i] < parray[mid])
{
issame--;
}
}
int pl = l, pr = mid + 1;
for (int i = l; i <= r; i++)
{
if (i == l)
{
num_left[d][i] = 0;
sum[d][i] = 0;
}
else
{
num_left[d][i] = num_left[d][i - 1];
sum[d][i] = sum[d][i - 1];
}
if (sg_node[d][i] < parray[mid])
{
num_left[d][i]++;
sum[d][i] += sg_node[d][i];
sg_node[d + 1][pl++] = sg_node[d][i];
}
else if (sg_node[d][i] > parray[mid])
{
sg_node[d + 1][pr++] = sg_node[d][i];
}
else
{
if (issame > 0)
{
issame--;
num_left[d][i]++;
sum[d][i] += sg_node[d][i];
sg_node[d + 1][pl++] = sg_node[d][i];
}
else
{
sg_node[d + 1][pr++] = sg_node[d][i];
}
}
}
Maketree(2 * o, d + 1, l, mid);
Maketree(2 * o + 1, d + 1, mid + 1, r);
}
long long sumleft, numleft;
int SGtree::Query(int i, int d, int x, int y, int k)
{
int l = node[i].l;
int r = node[i].r;
int mid = (l + r) >> 1;
long long temp = 0;
if (l == r)
{
return sg_node[d][x];
}
int lnum, ltornum;
if (x == node[i].l)
{
lnum = 0;
temp = sum[d][y];
}
else
{
lnum = num_left[d][x - 1];
temp = sum[d][y] - sum[d][x - 1];
}
ltornum = num_left[d][y] - lnum;
if (ltornum >= k)
{
return Query(i * 2, d + 1, l + lnum, l + lnum + ltornum - 1, k);
}
else
{
int a = x - l - lnum;
int b = y - x - ltornum;
numleft += ltornum;
sumleft += temp;
return Query(i * 2 + 1, d + 1, mid + a + 1, mid + a + b + 1, k - ltornum);
}
}
void solve(int x, int y)
{
int mid = (y - x + 2) >> 1;
numleft = 0;
sumleft = 0;
int m = tree.Query(1, 1, x, y, mid);
long long ans = m * numleft - sumleft;
long long temp = tree.sum[0][y] - tree.sum[0][x - 1] - sumleft;
ans += temp - m * (y - x + 1 - numleft);
cout << ans << endl;
}
void input()
{
int t, n, m, x, y, c = 0;
cin >> t;
while (t--)
{
tree.init();
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &tree.parray[i]);
tree.sg_node[1][i] = tree.parray[i];
tree.sum[0][i] = tree.sum[0][i - 1] + tree.parray[i];
}
sort(tree.parray + 1, tree.parray + n + 1);
tree.Maketree(1, 1, 1, n);
scanf("%d", &m);
cout << "Case #" << ++c << ':' << endl;
while (m--)
{
scanf("%d %d", &x, &y);
x++, y++;
solve(x, y);
}
cout << endl;
}
}
int main()
{
input();
return 0;
}