[国家集训队]middle

嘟嘟嘟

有谁能想到这题会用到主席树呢?(不愧是WJMZBMR出的题)

首先考虑如果区间是固定的话,中位数该怎么求。
没错,二分。如果大于当前二分值\(mid\)的数比小于\(mid\)的数多,说明\(mid\)还可以再变大,向右二分;否则向左二分。
如果我们把小于\(mid\)的数都标记成\(-1\),大于的标记成\(1\),那么只用判断这个区间的和是否\(\geqslant 0\)就行了。

但现在区间不固定。首先\([b + 1, c - 1]\)是一定要选的。对于\([a, b]\)\([c, d]\),因为要让中位数尽量大,所以应该选\([a, b]\)的最大后缀和以及\([c, d]\)的最大前缀和。

主要思路就是这些,但单次查询的复杂度是\(O(n \log{n})\)的,过不了。得想办法优化。

如果对每一个二分的值建一棵区间线段树(这里的二分在序列中的值中进行就行,而不是\(1\)\(1e9\),所以只用建\(n\)棵),把小于他的都标记成\(1\),大于标记成\(-1\),那么每一次查询就能达到\(O(\log ^ 2{n})\)了。
但是很显然这样空间开不下,而且预处理复杂度过高。所以现在得想办法减少预处理的时间。
如果把序列中的数排一个序,会发现对于相邻的两个不一样的数(因为数字可能有重),建的线段树只有一处不一样,而这一处不一样只会导致线段树中的一条链改变。所以我们只要单独把这条链提建出来就行了。
然后就会发现这其实就是一棵主席树呀。

于是这题就写完了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e4 + 5;
const int maxt = 2e6 + 5;
inline ll read()
{ll ans = 0;char ch = getchar(), last = ' ';while(!isdigit(ch)) {last = ch; ch = getchar();}while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - '0'; ch = getchar();}if(last == '-') ans = -ans;return ans;
}
inline void write(ll x)
{if(x < 0) x = -x, putchar('-');if(x >= 10) write(x / 10);putchar(x % 10 + '0');
}int n, _n, m, a[maxn], b[maxn], q[4];
vector<int> v[maxn];struct Tree
{int ls, rs;int sum, lmax, rmax;
}t[maxt];
int root[maxn], cnt = 0;
void pushup(int now)
{t[now].sum = t[t[now].ls].sum + t[t[now].rs].sum;t[now].lmax = max(t[t[now].ls].lmax, t[t[now].ls].sum + t[t[now].rs].lmax);t[now].rmax = max(t[t[now].rs].rmax, t[t[now].rs].sum + t[t[now].ls].rmax);
}
void build(int& now, int l, int r)
{if(!now) now = ++cnt;if(l == r) {t[now].sum = t[now].lmax = t[now].rmax = 1; return;}int mid = (l + r) >> 1;build(t[now].ls, l, mid);build(t[now].rs, mid + 1, r);pushup(now);
}
void insert(int old, int& now, int l, int r, int id)
{t[now = ++cnt] = t[old];if(l == r) {t[now].sum = t[now].lmax = t[now].rmax = -1; return;}int mid = (l + r) >> 1;if(id <= mid) insert(t[old].ls, t[now].ls, l, mid, id);else insert(t[old].rs, t[now].rs, mid + 1, r, id);pushup(now);
}
int querySum(int now, int l, int r, int L, int R)
{if(R < L) return 0;if(l == L && r == R) return t[now].sum;int mid = (l + r) >> 1;if(R <= mid) return querySum(t[now].ls, l, mid, L, R);else if(L > mid) return querySum(t[now].rs, mid + 1, r, L, R);else return querySum(t[now].ls, l, mid, L, mid) + querySum(t[now].rs, mid + 1, r, mid + 1, R);
}
int queryL(int now, int l, int r, int L, int R)
{if(l == L && r == R) return t[now].lmax;int mid = (l + r) >> 1;if(R <= mid) return queryL(t[now].ls, l, mid, L, R);else if(L > mid) return queryL(t[now].rs, mid + 1, r, L, R);else{int ret1 = queryL(t[now].ls, l, mid, L, mid);int ret2 = querySum(t[now].ls, l, mid, L, mid) + queryL(t[now].rs, mid + 1, r, mid + 1, R);return max(ret1, ret2);}
}
int queryR(int now, int l, int r, int L, int R)
{if(l == L && r == R) return t[now].rmax;int mid = (l + r) >> 1;if(R <= mid) return queryR(t[now].ls, l, mid, L, R);else if(L > mid) return queryR(t[now].rs, mid + 1, r, L, R);else{int ret1 = queryR(t[now].rs, mid + 1, r, mid + 1, R);int ret2 = querySum(t[now].rs, mid + 1, r, mid + 1, R) + queryR(t[now].ls, l, mid, L, mid);return max(ret1, ret2);}
}bool judge(int x)
{int ans1 = querySum(root[x], 1, n, q[1] + 1, q[2] - 1);int ans2 = queryR(root[x], 1, n, q[0], q[1]);int ans3 = queryL(root[x], 1, n, q[2], q[3]);return ans1 + ans2 + ans3 >= 0;
}
int solve()
{int L = 1, R = _n;while(L < R){int mid = (L + R + 1) >> 1;if(judge(mid)) L = mid;else R = mid - 1;}return L;
}int main()
{n = read();build(root[0], 1, n);for(int i = 1; i <= n; ++i) a[i] = b[i] = read();sort(b + 1, b + n + 1);_n = unique(b + 1, b + n + 1) - b - 1;for(int i = 1; i <= n; ++i){a[i] = lower_bound(b + 1, b + _n + 1, a[i]) - b;v[a[i]].push_back(i);}for(int i = 1; i <= _n; ++i){root[i] = root[i - 1];for(int j = 0; j < (int)v[i - 1].size(); ++j)insert(root[i], root[i], 1, n, v[i - 1][j]);}m = read();for(int i = 1, ans = 0; i <= m; ++i){for(int j = 0; j < 4; ++j) q[j] = read();for(int j = 0; j < 4; ++j) q[j] = (q[j] + ans) % n + 1;sort(q, q + 4);ans = b[solve()];write(ans), enter;}return 0;
}

转载于:https://www.cnblogs.com/mrclr/p/10074763.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java List<Object>去掉重复对象-java8

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 public List<String> removeStringListDupli(List<String> stringList) {Set<String> set new LinkedHashSet<&g…

Vue + webpack 项目配置化、接口请求统一管理

准备工作 需求由来&#xff1a; 当项目越来越大的时候提高项目运行编译速度、压缩代码体积、项目维护、bug修复......等等成为不得不考虑而且不得不做的问题。 又或者后面其他同事接手你的模块&#xff0c;或者改你的bug时避免人家看的眼痛以及心里千百句mamaipi...问候。 并且…

Python实现Adaboost

1.Adaboost概念 提升方法的思路是综合多个分类器&#xff0c;得到更准确的分类结果。 即“三个臭皮匠顶个诸葛亮”。《统计学习方法》称AdaBoost是提升算法的代表&#xff0c;所谓提升算法&#xff0c;指的是一种常用的统计学习方法&#xff0c;应用广泛且有效。在分类问题中&a…

Java List<T>去重方法,引用类型集合去重

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、实体类中要重写比较方法equals&#xff0c;最好也重写hashcode方法 public class WorkWeightDto implements Serializable {privat…

MyBatis知识点

一、MyBatis简介 1.1 框架概念 框架&#xff0c;就是软件的半成品&#xff0c;完成了软件开发过程中的通用操作&#xff0c;程序员只需很少或者不用进行加工就能够实现特定的功能&#xff0c;从而简化开发人员在软件开发中的步骤&#xff0c;提高开发效率。 1.2 常用框架 MVC…

android studio : clang++.exe: error: invalid linker name in argument '-fuse-ld=bfd

公司jenkins上的C编译器最近换成了clang&#xff0c;今天更新了代码发现本地的C/C代码用NDK编译不过了&#xff0c;提示&#xff1a; “clang.exe: error: invalid linker name in argument -fuse-ldbfd” 解决办法&#xff1a; 将Android.mk文件中的“LOCAL_LDFLAGS -fuse-ld…

Git知识点

一、Git简介 1.1 项目的版本管理 在项目开发过程中&#xff0c;项目没开发到一个节点就会对当前项目进行备份&#xff0c;这个备份就是项目的一个版本&#xff1b;当我们继续开发一个阶段后&#xff0c;再次进行备份&#xff0c;就生成新的版本——多个版本的集合就是项目的版…

(1)初始化项目

2019独角兽企业重金招聘Python工程师标准>>> &#xff08;1&#xff09;初始化项目 1 使用vue-cli初始化项目 vue init webpack my-renren得到以下输出&#xff1a; ? Project name my-renren ? Project description A Vue.js project ? Author neumeng <4048…

C语言变量

C语言二进制、八进制、十六进制详解 什么是二制制? 在数学计算中&#xff0c;二进制计数系统的公分母是最小的&#xff0c;它以2为基数。你还记得在小学或中学时所学的不同的计数系统吗?笔者在上小学时&#xff0c;曾在一堂数学课中学过以6为基数的计数系统&#xff1b;你先…

Spring Data JPA - 参考文档 地址

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Spring Data JPA - 参考文档 文档地址

JS内置方法(Array)

concat() 用于连接两个或多个数组&#xff0c;该方法不会改变现有的数组&#xff0c;而是返回被连接数组的一个副本。join() 把数组中的所有元素放入一个字符串&#xff0c;元素是通过指定的分隔符进行分隔的。若省略了分隔符参数&#xff0c;则使用逗号作为分隔符。push() 向…

模切ERP和免费OA系统是互相结合提高效率

模切ERP和免费OA系统是互相结合提高效率在模切行业中&#xff0c;模切ERP在管理上的作用占了很大的比重&#xff0c;但是免费OA在管理上的地位都不容忽视的。点晴OA的核心问题是如何提高日常的办公效率问题。因此点晴OA系统里包含的功能是非常全面&#xff0c;如&#xff1a;办…

maven知识点

一、Maven简介 1.1 在项目中如何导入jar包&#xff1f; 下载jar包 &#xff08;mvn&#xff09;将下载的jar包拷贝到项目中&#xff08;WEB-INF/lib&#xff09;选择jar文件–右键–Add as Library 1.2 传统导入jar包的方式存在什么问题&#xff1f; 步骤多&#xff08;相对…

使用SpringBoot yml配置文件

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.上一次我们已经使用SpringBoot实现了一个简单的HelloWord程序&#xff0c;辣么接下来我们简单的使用一下他的yml格式的配置文件。 2.在…

软件行业资讯

为什么只有设计师才能发明流行的新语言 先回顾一下知名编程语言的作者和创造时间&#xff1a;Fortran 语言&#xff0c;50年代&#xff0c;IBM 研究员&#xff1b;Lisp 语言&#xff0c;50年代&#xff0c;MIT 的教授和学生&#xff1b;C语言&#xff0c;70年代&#xff0c;贝尔…

spring知识点

一、Spring概述 1.1 web项目开发中的耦合度问题 在Servlet中需要调用service中的方法&#xff0c;则需要在Servlet类中通过new关键字创建Service的实例 public interface ProductService{public List<Product> listProducts(); }public class ProductServiceImpl1 imple…

Linux系统下的权限试题测试

不会做的留言&#xff0c;到时在发布答案&#xff01;一、 有两个参赛团队team1、team2&#xff0c;两个团队各3人, 这两个团队互相竞争&#xff0c;各需提交一份报告&#xff0c;每组成员可以修改自己团队内的所有文件&#xff0c;且不能让其他团队的人修改自己的文件内容&…

电子科大软件系统架构设计——软件建模详细设计

文章目录 软件建模详细设计概述软件建模详细设计目标软件建模详细设计原则开闭原则里氏 (Liskov) 替换原则依赖倒置原则接口分离原则单一职责原则最少知识原则&#xff08;迪米特法则&#xff09;高内聚原则松耦合原则可重用原则 软件建模详细设计内容 UML 软件静态结构视图建模…

YAML文件解析

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 YAML是“另一种标记语言”的外语缩写,YAML 是一种比JSON&#xff08;json多层次{ 与 [ 会被搞晕的&#xff09;更直观的表现形式&#xf…

120分钟React快速扫盲教程

在教程开端先说些题外话&#xff0c;我喜欢在学习一门新技术或读过一本书后&#xff0c;写一篇教程或总结&#xff0c;既能帮助消化&#xff0c;也能加深印象和发现自己未注意的细节&#xff0c;写的过程其实仍然是一个学习的过程。有个记录的话&#xff0c;在未来需要用到相关…