题目大意:有一个序列,包含多次询问。询问区间左右端点在规定区间里移动所得到的最大中位数的值。

  考虑对于每个询问,如何得到最优区间?枚举显然是超时的,只能考虑二分。

  中位数的定义是在一个序列中,比中位数小的数跟比它大的数一样多,由于我们要求的是最大的中位数,自然希望能找到一个区间,使得该区间内比该中位数大的数尽量多。

  二分中位数k,假设比k小的数记为-1,其余的数记为1,那么我们就是要寻找最大连续子序列和,若找到的最大的和>=0,则当前的k就是合法的。

  最大连续子序列和可以用线段树来维护,由于存在多组询问,每次建一棵线段树很慢,我们选择建主席树。初始时,把数按从小到大排好序,全部的数记为1,做到第i个数时,将第i-1个数记为-1,以此做下去。

  那么这样最终二分到的答案会不会不在指定的区间范围之中呢?

  肯定是不存在的,我们可以分类讨论。

   n为偶数:n = 4时,0 1 2 3,中位数的位置为2,如果答案在1-2之间,则会有更优的答案;如果在2-3之间,显然是不可能的。

   n为奇数:n = 3时,0 1 2 3 4,中位数的位置为2,分析同上。

#include <cstdio>
#include <cstdlib>
#include <algorithm> using namespace std; typedef long long LL;
const int maxn = ;
int n, a[maxn], b[maxn], root[maxn], q[];
struct Tree
{
int cnt;
int ml[maxn*], mr[maxn*], sum[maxn*], ls[maxn*], rs[maxn*];
Tree()
{
cnt = ;
}
void pushup(int rt)
{
ml[rt] = max(ml[ls[rt]], sum[ls[rt]]+ml[rs[rt]]);
mr[rt] = max(mr[rs[rt]], sum[rs[rt]]+mr[ls[rt]]);
sum[rt] = sum[ls[rt]]+sum[rs[rt]];
}
void build(int rt, int l, int r)
{
if (l == r)
{
ml[rt] = mr[rt] = sum[rt] = ;
return ;
}
int mid = (l+r)>>;
ls[rt] = ++cnt, build(ls[rt], l, mid);
rs[rt] = ++cnt, build(rs[rt], mid+, r);
pushup(rt);
}
void update(int las_rt, int rt, int l, int r, int p, int d)
{
if (l == r)
{
ml[rt] = mr[rt] = sum[rt] = d;
return ;
}
int mid = (l+r)>>;
if (p <= mid)
{
ls[rt] = ++cnt, rs[rt] = rs[las_rt];
update(ls[las_rt], ls[rt], l, mid, p, d);
}
else
{
ls[rt] = ls[las_rt], rs[rt] = ++cnt;
update(rs[las_rt], rs[rt], mid+, r, p, d);
}
pushup(rt);
}
int query_sum(int rt, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return sum[rt];
int mid = (l+r)>>, ret = ;
if (L <= mid)
ret += query_sum(ls[rt], l, mid, L, R);
if (R > mid)
ret += query_sum(rs[rt], mid+, r, L, R);
return ret;
}
int query_ml(int rt, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return ml[rt];
int mid = (l+r)>>;
if (R <= mid)
return query_ml(ls[rt], l, mid, L, R);
else
if (L > mid)
return query_ml(rs[rt], mid+, r, L, R);
else
return max(query_ml(ls[rt], l, mid, L, R), query_sum(ls[rt], l, mid, L, R)+query_ml(rs[rt], mid+, r, L, R));
}
int query_mr(int rt, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return mr[rt];
int mid = (l+r)>>;
if (R <= mid)
return query_mr(ls[rt], l, mid, L, R);
else
if (L > mid)
return query_mr(rs[rt], mid+, r, L, R);
else
return max(query_mr(rs[rt], mid+, r, L, R), query_sum(rs[rt], mid+, r, L, R)+query_mr(ls[rt], l, mid, L, R));
}
}T; bool cmp(const int &AI, const int &BI)
{
return a[AI] < a[BI];
} void build_tree()
{
root[] = ++T.cnt;
T.build(root[], , n);
for (int i = ; i <= n; ++i)
{
root[i] = ++T.cnt;
T.update(root[i-], root[i], , n, b[i-], -);
}
} bool check(int k, int q1, int q2, int q3, int q4)
{
int sum = ;
if (q2+ < q3)
sum += T.query_sum(root[k], , n, q2+, q3-);
sum += T.query_mr(root[k], , n, q1, q2);
sum += T.query_ml(root[k], , n, q3, q4);
return sum >= ;
} int main()
{
scanf("%d", &n);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]), b[i] = i;
sort(b+, b+n+, cmp);
build_tree();
int ans = ;
int task;
scanf("%d", &task);
while (task --)
{
scanf("%d %d %d %d", &q[], &q[], &q[], &q[]);
for (int i = ; i <= ; ++i)
q[i] = (q[i]+ans)%n+;
sort(q+, q++);
int l = , r = n;
while (l < r)
{
int mid = (l+r+)>>;
if (check(mid, q[], q[], q[], q[]))
l = mid;
else
r = mid-;
}
ans = a[b[l]];
printf("%d\n", ans);
}
return ;
}

最新文章

  1. ping环回地址和ping主机地址的区别
  2. 有人要分享pjax吗?
  3. pagerank
  4. 【转】ACM博弈知识汇总
  5. 代码高亮美化插件-----SyntaxHighlighter
  6. BizTalk开发系列(三十七) 性能监视器在BizTalk性能测试中的使用
  7. ruby -- 进阶学习(十)自定义路由中:new, :collection和:member的区别
  8. IIS下 Yii Url重写
  9. PHP中date函数参数详解
  10. Enum枚举
  11. Linux多线程实践(10) --使用 C++11 编写 Linux 多线程程序
  12. MySql事务的隔离级别及作用
  13. 重启报错:Failed to open /dev/initctl: No such device or address
  14. 补齐-Django之Model操作
  15. Sqoop入门
  16. 在JAVA中封装JSONUtil工具类及使用
  17. InkCanvas控件的使用
  18. 如何用js替换文本里的换行符 \n?
  19. [MySQL 5.6] GTID实现、运维变化及存在的bug
  20. Java 多线程 - synchronize 关键字

热门文章

  1. 利用Jsoup模拟跳过登录爬虫获取数据
  2. Python3 多进程
  3. Python设计模式中单例模式的实现及在Tornado中的应用
  4. 《secret》读书笔记
  5. ../include/squid_md5.h:27:2: error: #error Cannot find OpenSSL MD5 headers【squid安装中】
  6. [转载]锁无关的数据结构与Hazard指针——操纵有限的资源
  7. Nginx 原理篇
  8. ZOJ 1610 Count the Colors(区间染色)
  9. 使用Guava retryer优雅的实现接口重试机制
  10. 洛谷 P2788数学1(math1)- 加减算式 题解