# 划分树几道题目

typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const int INF = 1000000000;
#define lson l, m, dep + 1
#define rson m + 1, r, dep + 1
const int maxn = 100010;
const int deep = 30;

int t[deep][maxn];
int st[maxn];
int toleft[deep][maxn];

void build(int l, int r, int dep)
{
int i;
if (l == r) return;
int m = (r + l) >> 1;
int same = m - l + 1;//表示等于中间值而且被分入左边的个数
for (i = l; i <= r; i++)
if (t[dep][i] < st[m])
same--;
int lpos = l;
int rpos = m + 1;
for (i = l; i <= r; i++)
{
if (t[dep][i] < st[m])//比中间的数小，分入左边
t[dep + 1][lpos++] = t[dep][i];
else if (t[dep][i] == st[m] && same > 0)
{
t[dep + 1][lpos++] = t[dep][i];
same--;
}
else// if (t[dep][i] > st[m]) //比中间值大分入右边
t[dep + 1][rpos++] = t[dep][i];
toleft[dep][i] = toleft[dep][l - 1] + lpos - l;//从1到i放左边的个数
}
build(lson);
build(rson);
}

//查询区间第k大的数，[l,r]是大区间，[L,R]是要查询的小区间
int query(int L, int R, int k,int l, int r,int dep)
{
if (l == r) return t[dep][l];///!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
int m = (l + r) >> 1;
int cnt = toleft[dep][R] - toleft[dep][L - 1];//[L,R]中位于左边的个数
if (cnt >= k)
{
//l+要查询的区间前被放在左边的个数
int newl = l + toleft[dep][L - 1] - toleft[dep][l - 1];
//左端点加上查询区间会被放在左边的个数
int newr = newl + cnt - 1;
return query(newl, newr, k, lson);///!!!!!newl, newr
}
else
{
int newr = R + toleft[dep][r] - toleft[dep][R];
int newl = newr - (R - L - cnt);
return query(newl, newr, k - cnt, rson);///!!!!!!
}
}

int main()
{
int n, m;
int a, b;
int p = 1;
while (cin >> n)
{
CLR(t, 0);///
FE(i, 1, n)///
{
RI(t[0][i]);
st[i] = t[0][i];
}
sort(st + 1, st + n + 1);///
build(1, n, 0);///
printf("Case %d:\n",p++);
cin >> m;
REP(i, m)
{
RII(a, b);
printf("%d\n",query(a, b, (b - a) / 2 + 1, 1, n, 0));
}
}
}

typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const int INF = 1000000000;
const int maxn = 100010;
const int deep = 20;

#define lson l, m, dep + 1
#define rson m + 1, r, dep + 1

int t[deep][maxn];
int toleft[deep][maxn];
int st[maxn];
LL lsum[deep][maxn];
//LL sum[maxn];
LL ans;

void build(int l, int r, int dep)
{
if (l == r) {
lsum[dep][l] = t[dep][l];
return ;
}
int m = (l + r) >> 1;
int same = m - l + 1;
FE(i, l, r)
{
if (t[dep][i] < st[m])
same--;
lsum[dep][i] = t[dep][i];
if (i != l) lsum[dep][i] += lsum[dep][i - 1];
}
int lpos = l;
int rpos = m + 1;
FE(i, l, r)
{
if (t[dep][i] < st[m])
t[dep + 1][lpos++] = t[dep][i];
else if (t[dep][i] == st[m] && same > 0)
{
t[dep + 1][lpos++] = t[dep][i];
same--;
}
else
t[dep + 1][rpos++] = t[dep][i];
toleft[dep][i] = toleft[dep][l - 1] + lpos - l;///
}
build(lson);
build(rson);
}

int query(int L,int R, int k, int l, int r,int dep)
{
if (L == R ) return t[dep][L];
int cnt = toleft[dep][R] - toleft[dep][L - 1];
int m = (l + r) >> 1;

int ln1 = toleft[dep][L - 1] - toleft[dep][l - 1];
int rn1 = L - l - ln1;

int ln2 = cnt;
int rn2 = R - L + 1 - cnt;

if (cnt >= k)
{
if (rn2 > 0)
{
if (rn1 > 0)
ans += lsum[dep + 1][m + rn1 +rn2] - lsum[dep + 1][m + rn1];///@@@@///dep + 1
else ans += lsum[dep + 1][m + rn2];
}

int newl = l + ln1;
int newr = newl + cnt - 1;
return query(newl, newr, k, lson);
}
else
{
if (ln2 > 0)
{
if (ln1 > 0)
ans -= lsum[dep + 1][l - 1 +ln1 + ln2] - lsum[dep + 1][l - 1 + ln1];
else ans -= lsum[dep + 1][l - 1 + ln2];
}

int newr = R + toleft[dep][r] - toleft[dep][R];
int newl = newr - (R - L - cnt);
return query(newl, newr, k - cnt, rson);
}

}

int T;
int n, m;
int main()
{
int x, y;
cin >> T;
int p = 1;
while (T--)
{
RI(n);
//       CLR(t, 0,);///
//       CLR(toleft, 0);///
FE(i, 1, n)
{
RI(t[0][i]);
st[i] = t[0][i];
}
sort(st + 1, st + n + 1);
build(1, n, 0);///
printf("Case #%d:\n",p++);
RI(m);
REP(i, m)
{
RII(x, y);
x++;
y++;
ans = 0;
LL midval = query(x, y, (y - x) / 2 + 1, 1, n, 0);///0
if ((y - x + 1) % 2 == 0) ans -= midval;
cout << ans << endl;
}
printf("\n");
}
}


const int MAXN = 100010;
const int MOD = 1000000;

#define lson l, m, dep + 1
#define rson m + 1, r, dep + 1
int t[20][MAXN];
int st[MAXN];
int tol[20][MAXN];
LL lsum[20][MAXN];
LL ans;
int n, m;

void build(int l, int r, int dep)
{
if (l == r)
{
return ;
}
int m = (l + r) >> 1;
int same = (m - l + 1);
FE(i, l, r) if (st[m] > t[dep][i]) same--;
int lpos = l;
int rpos = m + 1;
FE(i, l, r)
{
if (t[dep][i] < st[m]) t[dep + 1][lpos++] = t[dep][i];
else if (t[dep][i] == st[m] && same > 0) t[dep + 1][lpos++] = t[dep][i], same--;
else t[dep + 1][rpos++] = t[dep][i];
tol[dep][i] = tol[dep][l - 1] + lpos - l;
}
FE(i, l, r) lsum[dep + 1][i] = lsum[dep + 1][i - 1] + t[dep + 1][i];
build(lson);
build(rson);
}

LL query(int L, int R, int k, int l, int r, int dep)
{
if (L == R) return t[dep][L];
int m = (r + l) >> 1;
int cnt = tol[dep][R] - tol[dep][L - 1];

int ln1 = tol[dep][L - 1] - tol[dep][l - 1];
int rn1 = L - l - ln1;

int ln2 = cnt;
int rn2 = R - L - cnt + 1;

if (cnt >= k)//toleft
{
if (rn2 > 0) ans += lsum[dep + 1][m + rn2 + rn1] - lsum[dep + 1][m + rn1];
int newl = l + tol[dep][L - 1] - tol[dep][l - 1];
int newr = newl + cnt - 1;
query(newl, newr, k, lson);
}
else//toright
{
if (ln2 > 0) ans -= lsum[dep + 1][l + ln2 + ln1 - 1] - lsum[dep + 1][l + ln1 - 1];
int newr = R + tol[dep][r] - tol[dep][R];
int newl = newr - (R - L - cnt);
query(newl, newr, k - cnt, rson);
}
}

int main()
{
int T;
RI(T);
int x, y;
int ncase = 1;
while (T--)
{

RI(n);
CLR(t, 0);
CLR(lsum, 0);
CLR(tol, 0);
FE(i, 1, n)
{
RI(st[i]);
t[0][i] = lsum[0][i] = st[i];
}
sort(st + 1, st + n + 1);
FE(i, 1, n) lsum[0][i] += lsum[0][i - 1];
build(1, n, 0);
RI(m);
printf("Case #%d:\n", ncase++);
while (m--)
{
RII(x, y);
x++;
y++;
ans = 0;
int mid = query(x, y, (y - x) / 2 + 1, 1, n, 0);
if ((y - x + 1) % 2 == 0) ans -= mid;
cout << ans << endl;
}
cout << endl;
}
}

typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const int INF = 1000000000;
const int maxn = 100010;
const int deep = 20;

#define lson l, m, dep + 1
#define rson m + 1, r, dep + 1

int t[deep][maxn];
int tol[deep][maxn];
int st[maxn];
int n;
void build(int l, int r, int dep)
{
if (l == r) return;
int m = (l + r) >> 1;
int same = m - l + 1;
FE(i, l, r)
if (t[dep][i] < st[m]) same--;
int lpos = l;
int rpos = m + 1;
FE(i, l, r)
{
if (t[dep][i] < st[m]) t[dep + 1][lpos++] = t[dep][i];
else if (t[dep][i] == st[m] && same > 0) { t[dep + 1][lpos++]=  t[dep][i]; same--; }
else t[dep + 1][rpos++] = t[dep][i];
tol[dep][i] = tol[dep][l - 1] + lpos - l;
}
build(lson);
build(rson);
}

int ans;
int h;
void query(int L, int R, int l, int r, intdep)
{
if (L == R)
{
if (t[dep][L] <= h)
ans++;
return ;
}
int m = (l + r) >> 1;
int cnt = tol[dep][R] - tol[dep][L - 1];

//   int ln1 = tol[dep][L - 1] - tol[dep][l - 1];
//   int rn1 = L - l - ln1;
//
//   int ln2 = cnt;
//   int rn2 = R - L - cnt + 1;
//
//   int lr = t[dep + 1][l - 1 + ln1 + ln2];
//   int rl = t[dep + 1][m + rn1 + 1];

if (st[m] > h)
{
int newl = l + tol[dep][L - 1] - tol[dep][l - 1];
int newr = newl + cnt - 1;
if (newl <= newr)///?！！！！！！！！！！！
query(newl, newr, lson);
}
else
{
ans += cnt;
int newr = R + tol[dep][r] - tol[dep][R];
int newl = newr - (R - L - cnt);
if (newl <= newr)///?！！！！！！！！！！！
query(newl, newr, rson);
}
}

int T;

int main()
{
int x, y, z;
int T;
int p = 1;
RI(T);
while (T--)
{
//初始化
printf("Case %d:\n",p++);
CLR(t, 0);
CLR(tol, 0);
int m;
RII(n, m);
FE(i, 1, n)///
{
RI(t[0][i]);
st[i] = t[0][i];
}
sort(st + 1, st + n + 1);
build(1, n, 0);

while (m--)
{
RIII(x, y, z);
h = z;
ans = 0;
query(++x, ++y, 1, n, 0);
cout << ans << endl;
}
}
}


• 本文已收录于以下专栏：

## 划分树几道题目

• guognib
• 2014年02月27日 19:22
• 700

## 几道经典线段树题目及代码2

• 2010年06月04日 10:54
• 6KB
• 下载

## 划分树模板

• 2015年04月01日 15:57
• 3KB
• 下载

## 主席树几道题目

• guognib
• 2013年12月04日 16:54
• 1288

## 划分树算法总结

• 2013年02月26日 17:07
• 607KB
• 下载

## 划分树学习（poj 2104，hdu 3473）

• zxy_snow
• 2011年08月12日 11:11
• 11302

## hdu 2665 划分树

Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To...

## 第k元素log(n)算法--划分树

• pi9nc
• 2013年10月10日 15:45
• 1158

## hdu 4417 划分树加二分 求区间内小于num的数的个数

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To...

举报原因： 您举报文章：划分树几道题目 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)