题目描述

一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。给你一个
长度为n的序列s。回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。位置也从0开始标号。我会使用一些方式强制你在线。

输入

第一行序列长度n。接下来n行按顺序给出a中的数。
接下来一行Q。然后Q行每行a,b,c,d,我们令上个询问的答案是
x(如果这是第一个询问则x=0)。
令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
将q从小到大排序之后,令真正的
要询问的a=q[0],b=q[1],c=q[2],d=q[3]。  
输入保证满足条件。
第一行所谓“排过序”指的是从小到大排序!
n<=20000,Q<=25000

输出

Q行依次给出询问的答案。

样例输入

5
170337785
271451044
22430280
969056313
206452321
3
3 1 0 2
2 3 1 4
3 1 4 0

样例输出

271451044
271451044
969056313
  对于一个序列,如果序列有奇数个数,那么中位数是中间那个数,如果有偶数个数,那么中位数是中间两个中后面那个。如果要判断M是否为合法的中位数,就把序列中>=M的数权值设为1,<M的数权值设为-1,只要有一段区间的最大连续子段和>=0,那么M就是合法的。因此求一段区间的中位数可以二分中位数是什么,只要rmax(a,b-1)+sum(b,c)+lmax(c+1,d)大于零那么这个数就可能成为中位数(其中sum表示区间和,lmax表示区间从左端点开始最大连续子段和,rmax表示区间从右端点开始最大连续子段和)。对于每次二分答案要将线段树中小于答案的数权值设为-1,其他数权值设为1,求上述最大连续子段和。但如果每次二分答案都重新建树显然太慢了,因此可以用主席树,每个时刻i的主席树表示以第i个数为中位数时线段树的状态,第一个时刻将所有位置置为1,然后下一时刻将最小的数那个位置权值置为-1,以此类推。每次二分答案只要查询对应时刻的主席树就好了。
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
int n,m;
int sum[5000010];
int lmx[5000010];
int rmx[5000010];
int ls[5000010];
int rs[5000010];
int root[50010];
int a,b,c,d;
int cnt;
int ans;
int p[5];
struct node
{int num;int id;
}s[20010];
bool cmp(node a,node b)
{return a.num<b.num;
}
void pushup(int rt)
{sum[rt]=sum[ls[rt]]+sum[rs[rt]];lmx[rt]=max(lmx[ls[rt]],sum[ls[rt]]+lmx[rs[rt]]);rmx[rt]=max(rmx[rs[rt]],sum[rs[rt]]+rmx[ls[rt]]);
}
int build(int l,int r)
{int rt=++cnt;if(l==r){sum[rt]=1;lmx[rt]=1;rmx[rt]=1;return rt;}int mid=(l+r)>>1;ls[rt]=build(l,mid);rs[rt]=build(mid+1,r);pushup(rt);return rt;
}
int updata(int pre,int l,int r,int k)
{int rt=++cnt;if(l==r){sum[rt]=-1;lmx[rt]=0;rmx[rt]=0;return rt;}ls[rt]=ls[pre];rs[rt]=rs[pre];int mid=(l+r)>>1;if(k<=mid){ls[rt]=updata(ls[pre],l,mid,k);}else{rs[rt]=updata(rs[pre],mid+1,r,k);}pushup(rt);return rt;
}
int query(int rt,int l,int r,int L,int R)
{if(L>R){return 0;}if(L<=l&&r<=R){return sum[rt];}int mid=(l+r)>>1;if(L>mid){return query(rs[rt],mid+1,r,L,R);}else if(R<=mid){return query(ls[rt],l,mid,L,R);}return query(ls[rt],l,mid,L,R)+query(rs[rt],mid+1,r,L,R);
}
int findl(int rt,int l,int r,int L,int R)
{if(L>R){return 0;}if(L<=l&&r<=R){return rmx[rt];}int mid=(l+r)>>1;int res=0;if(R>mid){res=findl(rs[rt],mid+1,r,L,R);}if(L<=mid){res=max(res,findl(ls[rt],l,mid,L,R)+query(rs[rt],mid+1,r,mid+1,R));}return res;
}
int findr(int rt,int l,int r,int L,int R)
{if(L>R){return 0;}if(L<=l&&r<=R){return lmx[rt];}int mid=(l+r)>>1;int res=0;if(L<=mid){res=findr(ls[rt],l,mid,L,R);}if(R>mid){res=max(res,findr(rs[rt],mid+1,r,L,R)+query(ls[rt],l,mid,L,mid));}return res;
}
bool check(int x,int a,int b,int c,int d)
{int res=0;res+=query(root[x],1,n,b,c);res+=findl(root[x],1,n,a,b-1);res+=findr(root[x],1,n,c+1,d);if(res>=0){return true;}return false;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&s[i].num);s[i].id=i;}root[1]=build(1,n);sort(s+1,s+1+n,cmp);for(int i=2;i<=n;i++){root[i]=root[i-1];root[i]=updata(root[i],1,n,s[i-1].id);}scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%d%d%d%d",&a,&b,&c,&d);p[1]=(a+ans)%n;p[2]=(b+ans)%n;p[3]=(c+ans)%n;p[4]=(d+ans)%n;sort(p+1,p+5);a=p[1]+1;b=p[2]+1;c=p[3]+1;d=p[4]+1;int l=1;int r=n;ans=0;while(l<=r){int mid=(l+r)>>1;if(check(mid,a,b,c,d)){l=mid+1;ans=mid;}else{r=mid-1;}}ans=s[ans].num;printf("%d\n",ans);}
}

转载于:https://www.cnblogs.com/Khada-Jhin/p/9493055.html

BZOJ2653middle——二分答案+可持久化线段树相关推荐

  1. P3834 【模板】可持久化线段树 2(整体二分做法)

    P3834 [模板]可持久化线段树 2(主席树) 我们详细讲讲这个整体二分如何求区间第k小 我们都知道二分可以求出区间里某个想要的值,如果有很多询问,我们对每个询问都进行二分,复杂度就是O(QNlog ...

  2. 可持久化线段树——主席树

    前言: 最近心(po)血(yu)来(ya)潮(li)学习了一下主席树.(再不学就落伍了) 主席树,即可持久化线段树,支持维护和查询区间的第\(k\)大(小).区间不同种类个数等,基于线段树的思想之上 ...

  3. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  4. jzoj 5850.【NOIP提高组模拟2018.8.25】e 可持久化线段树+lca

    Description Input Output Data Constraint 分析: 最小连通块可以看作是所有点到他们的 lca l c a lca路径的并集,因为是取最小值,所以重复的不会有贡献 ...

  5. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  6. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  7. 【NOI2018】你的名字【后缀自动机】【可持久化线段树合并】【乱搞】

    题意:给一个串 SSS,qqq 次询问,每次给定串 TTT 和 l,rl,rl,r ,求有多少个本质不同的串是 TTT 的子串而不是 Sl-rS_{l\dots r}Sl-r​ 的子串. ∣S∣≤5× ...

  8. 【用学校抄作业带你走进可持久化线段树(主席树)】可持久化线段树概念+全套模板+例题入门:[福利]可持久化线段树)

    我似乎很少写这种算法博客 可持久化线段树概念 概念介绍(类比帮助理解) 简单分析一下时间和空间复杂度(内容池) 模板 结构体变量 建树模板 单点修改模板 单点查询模板 区间修改模板(pushup) 区 ...

  9. P3834-【模板】可持久化线段树 1(主席树)

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P3834 题意 给定一个长度为n的序列,有m个询问,求一个区间内的第k ...

最新文章

  1. 万万没想到,钉钉居然是个AI平台
  2. cmake / target_** 中的 PUBLIC,PRIVATE,INTERFACE
  3. javascript中的模块系统
  4. how debug option is handled - handle_debug
  5. 计算机网络之传输层:2、UDP协议
  6. TEN网格数据导入oracle,开源-Solidity 分散的oracle网络的示例链链接。-糯米PHP
  7. 索引体积_米家温湿度计体积虽小,耗电不小,如果经常离线,换颗电池吧
  8. 开源原生JavaScript插件-CJPCD(省市区联动)
  9. css手型指针_前端基础面试题(HTML+CSS部分)
  10. microsoft azure Media Services 媒体服务解决方案
  11. 链路层发现协议LLDP
  12. 【第四组】用例文档+功能说明书+技术说明书:查看导入的图片,工作序号:001,2017/7/11...
  13. 测试小故事82:好好说话
  14. win10 计算机组策略,win10家庭版系统找不到组策略gpedit.msc的解决方法
  15. 按位与运算()和求余运算(%)的联系
  16. AnimationController
  17. 全国计算机技术与软件专业资格(水平)考试报考指南
  18. JWT、JWE、JWS 、JWK 到底是什么?该用 JWT 还是 JWS?
  19. python推箱子游戏顶层设计子层设计_python实现推箱子游戏
  20. 用一部电影让你了解综合实践活动课

热门文章

  1. 禁用 Bootstrap 模态框(Modal) 点击空白时自动关闭
  2. 09 高效的PL/SQL程序设计
  3. 使用for of循环遍历获取的nodeList,配置babel编译,webpack打包之后在iphone5下报错...
  4. linux学习之用户的切换
  5. [每天一个知识点]31-乱七八糟-如何判断预言有效
  6. OSwatcher on Exadata
  7. Asp.net MVC中使用Razor Generator实现View的单元测试
  8. 【原创】ASP.NET C# 对SQL/ACCESS 数据库的备份和还原函数
  9. Windows Server 2008 Server Core模式
  10. tornado和subprocess实现程序的非堵塞异步处理