[洛谷P2839][国家集训队]middle
题目大意:给你一个长度为$n$的序列$s$。$Q$个询问,问在$s$中的左端点在$[a,b]$之间,右端点在$[c,d]$之间的子段中,最大的中位数。 强制在线。
题解:区间中位数?二分答案,如果询问区间是给定的,对于每个询问,二分答案是多少,然后只要求出这个区间中有多少个数比二分的数大就行了,这就可以对每一个值建一棵主席树,把比它小的赋成$-1$,大于等于的赋成$1$,只需要区间和,就可以在$O(\log_2 n)$的时间判断一个解了。
但区间不给定。怎么办?注意到,$[b+1,c-1]$的值是必选的。所以一下这个区间的和是一定会产生贡献的。
而对于$[a,b],[c,d]$,因为要让中位数尽可能的大。所以,要让这里面的数比二分的答案大的数尽可能多。
也就是说,需要找一个$[a,b]$的最大后缀和,$[c,d]$的最大前缀和。这三个值的和就是给的询问中所有字段中对于二分的答案的最大的值了(也就是比二分答案大的数的个数减去比二分答案小的数的个数),也就是最优解。
问题是,我们二分的中位数不一定在询问的范围当中,会不会最后的答案不在这个区间内呢? 其实是不会的,如果区间外有个数满足要求,那么区间内一定会有个数大于等于它,显然区间内的那个数最优,而且也是满足中位数的要求的
卡点:1.求区间最大前缀和以及区间最大后缀和的线段树(主席树),的判断返回值条件和分治方法和普通的不同,而我按普通的在写
2.我二分的答案是这个数是所有数中第几大的,然后就把$lastans$赋成了这个(应该赋成这个数是多少)
3.洛谷有锅,一模一样的代码在洛谷上$30$[点击查看],在$darkbzoj$和$bzoj$上$AC$[点击查看](虽然后来也在洛谷上过了。。。。)
C++ Code:
#include <cstdio>
#include <algorithm>
#define maxn 200100
#define N 3001500
using namespace std;
int root[maxn], lc[N], rc[N];
int idx;
bool flag;
struct node {
int r, sum, l; //r后缀,l前缀
inline bool operator == (node rhs) {return (r == rhs.r && sum == rhs.sum && l == rhs.l);}
} V[N], err; int n, Q, s[maxn], rnk[maxn];
int p[5], lastans = 0, ans; inline bool cmp(int a, int b) {return s[a] < s[b];}
inline int max(int a, int b) {return a > b ? a : b;} void update(int rt) {
V[rt].r = max(V[rc[rt]].r, V[rc[rt]].sum + V[lc[rt]].r);
V[rt].l = max(V[lc[rt]].l, V[lc[rt]].sum + V[rc[rt]].l);
V[rt].sum = V[lc[rt]].sum + V[rc[rt]].sum;
}
void build(int &rt, int l, int r) {
rt = ++idx;
if (l == r) {
V[rt].r = V[rt].sum = V[rt].l = 1;
return ;
}
int mid = l + r >> 1;
build(lc[rt], l, mid);
build(rc[rt], mid + 1, r);
update(rt);
}
void add(int &rt, int l, int r, int p) {
lc[++idx] = lc[rt], rc[idx] = rc[rt], rt = idx;
if (l == r) {
V[rt].r = V[rt].sum = V[rt].l = -1;
return ;
}
int mid = l + r >> 1;
if (p <= mid) add(lc[rt], l, mid, p);
else add(rc[rt], mid + 1, r, p);
update(rt);
}
int a, b, c, d;
node ask(int rt, int l, int r, int L, int R) {
if (!rt || l > r || L > R) return err;
if (L == l && R == r) return V[rt];
int mid = l + r >> 1;
if (R <= mid) return ask(lc[rt], l, mid, L, R);
if (L > mid) return ask(rc[rt], mid + 1, r, L, R);
node ans = ask(lc[rt], l, mid, L, mid), tmp = ask(rc[rt], mid + 1, r, mid + 1, R);
ans.l = max(ans.l, ans.sum + tmp.l);
ans.r = max(tmp.r, tmp.sum + ans.r);
ans.sum = ans.sum + tmp.sum;
return ans;
}
bool check(int mid) {
int tmp = ask(root[mid], 1, n, a, b).r + ask(root[mid], 1, n, b + 1, c - 1).sum + ask(root[mid], 1, n, c, d).l;
return tmp >= 0;
}
int main() {
scanf("%d", &n);
build(root[1], 1, n);
for (int i = 1; i <= n; i++) scanf("%d", &s[i]), rnk[i] = i;
sort(rnk + 1, rnk + n + 1, cmp);
for (int i = 2; i <= n; i++) {
root[i] = root[i - 1];
add(root[i], 1, n, rnk[i - 1]);
}
scanf("%d", &Q);
while (Q --> 0) {
scanf("%d%d%d%d", &a, &b, &c, &d);
p[0] = (a + lastans) % n + 1, p[1] = (b + lastans) % n + 1, p[2] = (c + lastans) % n + 1, p[3] = (d + lastans) % n + 1;
sort(p, p + 4);
a = p[0], b = p[1], c = p[2], d = p[3];
int L = 1, R = n;
while (L <= R) {
int mid = L + R + 1 >> 1;
if (check(mid)) {
L = mid + 1;
ans = mid;
} else R = mid - 1;
}
printf("%d\n", s[rnk[ans]]);
lastans = s[rnk[ans]];
}
return 0;
}
[洛谷P2839][国家集训队]middle的更多相关文章
- 洛谷P2839 [国家集训队]middle 主席树_二分
Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...
- [洛谷2839/国家集训队]middle
Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之 ...
- P2839 [国家集训队]middle
P2839 [国家集训队]middle 好妙的题啊,,,, 首先二分一个答案k,把数列里>=k的数置为1,=0就是k>=中位数,<0就是k<中位数 数列的最大和很好求哇 左边的 ...
- 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)
洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...
- [洛谷P1527] [国家集训队]矩阵乘法
洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...
- 洛谷P1501 [国家集训队]Tree II(LCT,Splay)
洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...
- 洛谷P2619 [国家集训队2]Tree I(带权二分,Kruscal,归并排序)
洛谷题目传送门 给一个比较有逼格的名词--WQS二分/带权二分/DP凸优化(当然这题不是DP). 用来解决一种特定类型的问题: 有\(n\)个物品,选择每一个都会有相应的权值,需要求出强制选\(nee ...
- 洛谷 P1407 [国家集训队]稳定婚姻 解题报告
P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...
- 洛谷 P1852 [国家集训队]跳跳棋 解题报告
P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...
随机推荐
- 【实现高可效的代理模式-Squid】
普通正向代理 首先安装squid代理软件包: 端口控制 在squid server端作端口访问控制,把默认的3128端口改为1000端口 同时把squid服务代理端口添加到selinux安全子系统的允 ...
- 【ISIS(中间系统到中间系统)路由链路状态信息协议初识】
ISIS单区域的基本配置 一:根据项目需求,考虑到组网的规模和条件,部署ISIS单区域的拓扑图如下: 二:配置 1:首先对RTA进行配置,在系统视图创建ISIS进程:进入ISIS配置视图,指定IS的级 ...
- 解决百度编辑器ueditor插入视频网址保存不了问题
问题:如下图,在百度编辑器中插入视频,视频网址可以识别,但是提交内容后视频却显示不了. 解决:这个问题主要是编辑器中会过滤一些html标签,所以可以给标签添加白名单. 修改 ueditor.confi ...
- Python学习:运算符
简单运算符: +(加) 两个对象相加 -(减) 从一个数中减去另一个数,如果第一个操作数不存在,则假定为零 *(乘) 给出两个数的乘积,或返回字符串重复指定次数后的结果 Eg.'haha' * 3 ...
- Go web表单验证
开发Web的一个原则就是,不能信任用户输入的任何信息,所以验证和过滤用户的输入信息就变得非常重要 必填字段 if len(r.Form["username"][0])==0{ // ...
- vuls安装记录
第一步安装go环境apt-get install golang-go(显示出错,go版本apt安装太低,apt-get purge golang-go卸载后手动安装,必须1.8.3以上) 还需将/us ...
- 【7-10 PAT】树的遍历
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(≤30),是二叉树中结点的个数.第二行给出其后序遍历序列.第三 ...
- 关于 SSH Server 的整体设定
# . 关于 SSH Server 的整体设定,包含使用的 port 啦,以及使用的密码演算方式 Port # SSH 预设使用 这个 port,您也可以使用多的 port ! # 亦即重复使用 po ...
- 通过数据库恢复SharePoint网站
SharePoint网站一般包含很多个数据库,最主要的有3个,分别是SharePoint_Admin_Content(管理中心数据库),SharePoint_Config(配置数据库)和 ...
- Win10开发笔记(一):一些VS2015中可能遇到的问题
Win10开发者交流群:53078485 一.VS2015部署Win10程序到手机出现“0x80073CFD”错误解决方案 在VS2015 RC中创建了Windows Universal程序,部署到手 ...