传送门

P2839 [国家集训队]middle

题解

遇到求中位数,一般套路性的方法是二分答案,然后求出该数在区间内的排名,

但是此题稍微有点区别,区间大小不确定,所以我们用到一个更万能的解决中位数问题的套路方法,

设<mid的数为-1,≥mid的数为1,得到b数组,那么若该区间的和S≥0,则该区间中位数≥mid,若S<0,则该区间中位数<mid;

对于的区间,首先区间内的值肯定得加上,然后,要让中位数最大化,也就是让S尽可能大,

所以还要加上内的最大后缀和内的最大前缀,然后判断S正负;

区间和、最大前缀后缀可以用线段树维护,这个简单;

那么b数组怎么求呢?把a数组离散化后,总共有不超过n个mid,对于每个mid都有个不同的b数组,

建n棵线段树?时间空间都过不去;

考虑从,可以发现只有排名为mid的数会从1变为-1,所以可以用主席树求出每一棵树,复杂度

查询单次复杂度,所以总复杂度

并不需要写3种线段树,因为线段树内维护最大前缀后缀时要用到区间和,所以你可以用一棵线段树维护三个值,方便调用;

查询函数也不需要分别写3个,只需一个函数返回3个值,复杂度都一样,并且这题常数要求并不苛刻(5625000*常数),常数大一点随便过。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define MAXN 20005
using namespace std;
inline ll read(){ll x=0;bool f=1;char s=getchar();while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();return f?x:-x;
}
int n,q,IN,root[MAXN],in[5],id;
ll a[MAXN],b[MAXN],ans;
vector<int>c[MAXN];
struct itn{int ls,rs,s,pr,su;itn(){}itn(int L,int R,int S,int P,int U){ls=L,rs=R,s=S,pr=P,su=U;}
}t[MAXN*20];
map<ll,int>mp;
inline void build(int x,int l,int r){if(l==r){t[x].s=t[x].pr=t[x].su=1;return;}int mid=(l+r)>>1;t[x].ls=++IN,t[x].rs=++IN;build(t[x].ls,l,mid),build(t[x].rs,mid+1,r);t[x].s=t[t[x].ls].s+t[t[x].rs].s;t[x].pr=max(t[t[x].ls].pr,t[t[x].ls].s+t[t[x].rs].pr);t[x].su=max(t[t[x].rs].su,t[t[x].rs].s+t[t[x].ls].su);
}
inline void add(int x,int y,int l,int r,int a){if(l==r){t[x].s=t[x].pr=t[x].su=-1;return;}int mid=(l+r)>>1;if(a<=mid)t[x].ls=++IN,t[x].rs=t[y].rs,add(t[x].ls,t[y].ls,l,mid,a);else t[x].ls=t[y].ls,t[x].rs=++IN,add(t[x].rs,t[y].rs,mid+1,r,a);t[x].s=t[t[x].ls].s+t[t[x].rs].s;t[x].pr=max(t[t[x].ls].pr,t[t[x].ls].s+t[t[x].rs].pr);t[x].su=max(t[t[x].rs].su,t[t[x].rs].s+t[t[x].ls].su);
}
inline itn query(int x,int l,int r,int a,int b){if(a>b)return itn(a,b,0,0,0);if(l==a&&r==b)return itn(a,b,t[x].s,t[x].pr,t[x].su);int mid=(l+r)>>1;if(a<=mid){if(b>mid){itn u=query(t[x].ls,l,mid,a,mid),v=query(t[x].rs,mid+1,r,mid+1,b);return itn(a,b,u.s+v.s,max(u.pr,u.s+v.pr),max(v.su,v.s+u.su));}else return query(t[x].ls,l,mid,a,b);}else return query(t[x].rs,mid+1,r,a,b);
}
int main()
{n=read();for(int i=1;i<=n;i++)a[i]=read(),mp[a[i]];map<ll,int>::iterator it;for(it=mp.begin();it!=mp.end();it++)b[++id]=it->first,it->second=id;for(int i=1;i<=n;i++)a[i]=mp[a[i]],c[a[i]].push_back(i);root[1]=++IN,build(IN,1,n);for(int i=2;i<=id;i++){root[i]=root[i-1];for(int j=0;j<c[i-1].size();j++){int x=++IN;add(x,root[i],1,n,c[i-1][j]),root[i]=x;}}q=read();while(q--){for(int i=0;i<4;i++)in[i]=(read()+ans)%(1ll*n)+1;sort(in,in+4);int l=1;for(int i=15;i>=0;i--)if(l+(1<<i)<=id){int o=l+(1<<i),sum=query(root[o],1,n,in[1]+1,in[2]-1).s;sum+=query(root[o],1,n,in[0],in[1]).su+query(root[o],1,n,in[2],in[3]).pr;if(sum>-1)l=o;}printf("%lld\n",ans=b[l]);}return 0;
}

[国家集训队]middle——中位数思维题相关推荐

  1. P2839 [国家集训队]middle(二分 套 主席树)

    P2839 [国家集训队]middle 有一个长度为nnn的序列,有mmm次询问,每次询问a,b,c,da, b, c, da,b,c,d,为l∈[a,b],r∈[c,d]l \in [a, b], ...

  2. 洛谷P2839 [国家集训队]middle(主席树)

    P2839 [国家集训队]middle 我们可以考虑二分中位数 checkcheckcheck 答案,那么我们对于某个值 midmidmid ,把 [l,r][l,r][l,r] 内的所有小于 mid ...

  3. [国家集训队]middle(二分+主席树[中位数思维题])

    文章目录 点击查看 solution code 点击查看 solution 简单口胡一下就跑 考虑二分答案ansansans 区间[x1,x2],x1∈[a,b],x2∈[c,d][x1,x2],x1 ...

  4. 可持久化普通线段树 ---- P2839 [国家集训队]middle 可持久化普通线段树 + 二分 求中位数最大值

    题目链接 题目大意: 解题思路: 这个题思路很妙!! 首先我们假设只有一次询问怎么做? 那么我们可以二分出这个最大值midmidmid,然后把大于等于midmidmid设置成111,把小于midmid ...

  5. [国家集训队]middle

    嘟嘟嘟 有谁能想到这题会用到主席树呢?(不愧是WJMZBMR出的题) 首先考虑如果区间是固定的话,中位数该怎么求. 没错,二分.如果大于当前二分值\(mid\)的数比小于\(mid\)的数多,说明\( ...

  6. bzoj 2653 洛谷 P2839 [国家集训队] middle

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2381  Solved: 1340 [Submit][Status][Di ...

  7. luogu2839 [国家集训队]middle

    题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排 ...

  8. [bzoj 2653][国家集训队]middle

    传送门 Description 一个长度为\(n\)的序列\(a\),设其排过序之后为\(b\),其中位数定义为\(b[n/2]\),其中\(a,b\)从\(0\)开始标号,除法取下整. 给你一个长度 ...

  9. P2839 [国家集训队]middle

    题面 • 提一下静态区间第k小的nlog2n的做法: 1. 建关于排名的主席树(按排名顺序建树). 2. 二分答案. • 这样做静态区间第k小的虽然有些ZZ,但它的意义在于将线段树   维护的对象改变 ...

  10. P2839 [国家集训队]middle 二分 + 主席树 在值域上建区间

    传送门 文章目录 题意: 思路: 题意: 思路: 我们先解决怎么判断中位数的问题,我们可以二分一个midmidmid,将<mid<mid<mid的值都变成−1-1−1,其他的数都变成 ...

最新文章

  1. SQL点滴12—SQL Server备份还原数据库中的小把戏
  2. java经典算法四十题
  3. 建模步骤_【设计课堂】游戏手柄建模,看这14个步骤图就够了!
  4. JQuery插件开发学习
  5. 在Ocelot中使用自定义的中间件(一)
  6. [蓝桥杯][算法提高VIP]数组替换-模拟
  7. linux中sort命令实例,Linux命令之排序命令sort使用实例
  8. 好看的简图动态背景图床源码 多接口聚合图床
  9. 化敌为友,微软出手优化 Chrome!
  10. ERROR 126 (HY000) at line 1: Incorrect key file for table '/tmp/#sql_7b09_0.MYI'; try to repair it
  11. jquery 上下无缝滚动
  12. 做了三年前端开发后,我选择回家创业
  13. 打开excel很慢的解决方法
  14. 智云通CRM:如何与客户建立信任关系?
  15. 【读书笔记】《杜月笙全传》读书笔记
  16. Win10输入法无法选择,右下角出现叉号,提示IME被禁用
  17. 数据产品经理类型划分和工作汇报框架
  18. FileSystemWatcher的Created事件问题
  19. 2020年第十七届中国研究生数学建模竞赛C题 面向康复工程的脑信号分析和判别建模
  20. proteus三输入与非门名字_Proteus所有元件名称

热门文章

  1. css如何使图片在右下角,这个右下角折角用css怎么画出来?
  2. 【Java愚公】gitlab关闭注册功能
  3. 服务器虚拟化的分类宿主模型,虚拟化分类
  4. python定义函数及调用函数
  5. Switch分支判断学习心得
  6. 自己做的SIP软电话
  7. 都说ApiPost香,它到底香在哪里?
  8. Google File System谷歌文件系统基本简述
  9. 安卓逆向_2 --- Androidkiller,apktool、dex2jar、jd-gui、jadx反编译工具 的 安装、设置及使用教程...
  10. java getbytes 编码_Java String getBytes() encoding 编码转换