题面:https://vjudge.net/problem/HYSBZ-2653

博客:https://blog.csdn.net/litble/article/details/78984846

这个题很明显不能建n棵动态开点的线段树,因为每颗线段树点分布都很密集,这样相当于都是满二叉树。但是,我们可以发现,相邻的每颗线段树只有一个位置不同,这样我们就可以用主席树了。主席树相当于每次只多开了O(logn)个节点就能新开一棵线段树。

代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 100010;
struct SegementTree {
int lson, rson;
int sum, lsum, rsum;
};
SegementTree tr[maxn * 200];
int tot = 0, n;
int root[maxn];
struct res {
int sum, val;
};
struct node {
int val, pos;
bool operator < (const node& rhs) const {
return val < rhs.val;
}
};
node a[maxn];
int b[5];
void pushup(int x) {
int ls = tr[x].lson, rs = tr[x].rson;
tr[x].sum = tr[ls].sum + tr[rs].sum;
tr[x].lsum = max(tr[ls].lsum, tr[ls].sum + tr[rs].lsum);
tr[x].rsum = max(tr[rs].rsum, tr[rs].sum + tr[ls].rsum);
}
void build(int now, int l, int r) {
if(l == r) {
tr[now].sum = tr[now].lsum= tr[now].rsum = 1;
return;
}
int mid = (l + r) >> 1;
tr[now].lson = ++tot;build(tot, l, mid);
tr[now].rson = ++tot;build(tot, mid + 1, r);
pushup(now);
}
void insert(int lnow, int rnow, int l, int r, int pos, int val) {
tr[rnow] = tr[lnow];
if(l == r) {
tr[rnow].sum = tr[rnow].lsum = tr[rnow].rsum = val;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) {
tr[rnow].lson = ++tot;
insert(tr[lnow].lson, tot, l, mid, pos ,val);
} else {
tr[rnow].rson = ++tot;
insert(tr[lnow].rson, tot, mid + 1, r, pos, val);
}
pushup(rnow);
}
int query_sum(int now, int l, int r, int ql, int qr) {
if(l >= ql && r <= qr) {
return tr[now].sum;
}
int mid = (l + r) >> 1;
int ans = 0;
if(ql <= mid) ans += query_sum(tr[now].lson, l, mid, ql, qr);
if(qr > mid) ans += query_sum(tr[now].rson, mid + 1, r, ql, qr);
return ans;
}
res query_lsum(int now, int l, int r, int ql, int qr) {
if(l >= ql && r <= qr) {
return (res){tr[now].sum, tr[now].lsum};
}
int mid = (l + r) >> 1;
res ans = (res){0, -INF}, tmp = (res){0, -INF};
if(ql <= mid) ans = query_lsum(tr[now].lson, l, mid, ql, qr);
if(qr > mid) tmp = query_lsum(tr[now].rson, mid + 1, r, ql, qr);
ans.val = max(ans.val, ans.sum + tmp.val);
ans.sum += tmp.sum;
return ans;
}
res query_rsum(int now, int l, int r, int ql, int qr) {
if(l >= ql && r <= qr) {
return (res){tr[now].sum, tr[now].rsum};
}
int mid = (l + r) >> 1;
res ans = (res){0, -INF}, tmp = {0, -INF};
if(ql <= mid) ans = query_rsum(tr[now].lson, l, mid, ql, qr);
if(qr > mid) tmp = query_rsum(tr[now].rson, mid + 1, r, ql, qr);
ans.val = max(tmp.val, ans.val + tmp.sum);
ans.sum += tmp.sum;
return ans;
}
int solve(int x) {
int tmp1 = 0, tmp2 = 0, tmp3 = 0;
if(b[1] + 1 < b[2]) tmp1 = query_sum(root[x], 0, n - 1, b[1] + 1, b[2] - 1);
tmp2 = query_lsum(root[x], 0, n - 1, b[2], b[3]).val;
tmp3 = query_rsum(root[x], 0, n - 1,b[0], b[1]).val;
if(tmp1 + tmp2 + tmp3 >= 0) return 1;
return 0;
}
int main() {
int m;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i].val);
a[i].pos = i;
}
sort(a, a + n);
root[0] = ++tot;
build(tot, 0, n - 1);
for (int i = 1; i < n; i++) {
root[i] = ++tot;
insert(root[i - 1], tot, 0, n - 1, a[i - 1].pos, -1);
}
int ans = 0;
scanf("%d", &m);
while(m--) {
for (int i = 0; i < 4; i++) {
scanf("%d", &b[i]);
b[i] = (b[i] + ans) % n;
}
sort(b, b + 4);
int l = 0, r = n - 1;
while(l < r) {
int mid = (l + r + 1) >> 1;
if(solve(mid))l = mid;
else r = mid - 1;
}
ans = a[l].val;
printf("%d\n", ans);
} }
//6
//1 2 3 4 5 6
//1
//0 1 4 5

  

bzoj 2653 middle(主席树)的更多相关文章

  1. bzoj 2653: middle (主席树+二分)

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2522  Solved: 1434[Submit][Status][Disc ...

  2. BZOJ 2653: middle(主席树+二分答案)

    传送门 解题思路 首先可以想到一种暴力做法,就是询问时二分,然后大于等于这个值的设为1,否则设为-1,然后就和GSS1那样统计答案.但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做 ...

  3. BZOJ 2653: middle 主席树 二分

    https://www.lydsy.com/JudgeOnline/problem.php?id=2653 因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和 ...

  4. BZOJ 2653: middle [主席树 中位数]

    传送门 题意: 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右 ...

  5. BZOJ 2653 middle | 主席树

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题解: 设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前an ...

  6. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  7. bzoj 2653 middle 二分答案 主席树判定

    判断中位数是否可行需要将当前的解作为分界,大于其的置为1,小于为-1,然后b-c必选,ab,cd可不选,这个用线段树判定就好 但不能每次跑,所以套主席树,按权值排序,构建主席树,更新时将上一个节点改为 ...

  8. BZOJ 2653 middle 二分答案+可持久化线段树

    题目大意:有一个序列,包含多次询问.询问区间左右端点在规定区间里移动所得到的最大中位数的值. 考虑对于每个询问,如何得到最优区间?枚举显然是超时的,只能考虑二分. 中位数的定义是在一个序列中,比中位数 ...

  9. [BZOJ2653]middle 主席树+二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2042  Solved: 1123[Submit][Status][Disc ...

随机推荐

  1. vmware centos 连网方式

    1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址. #dhclient 自动获取ip地址命令 #ifconfig 查询系统里网卡信息,i ...

  2. mac下用brew安装mongodb

    分享到:QQ空间新浪微博腾讯微博人人网微信 mac 下安装mongoDB一般俩种方法. (1)下载源码,解压,编译,配置,启动 比较艰难的一种模式. (2)brew install mongodb , ...

  3. git教程1-git工作原理与初始化仓库

    一.git工作原理 1.git是版本控制器,因此管理的是版本,每一次提交commit就是新建一个版本. 2.分支:git主分支可以存放一个阶段已经完成好的版本,而修改版本则放置在次分支上. 3.融合: ...

  4. Codeforces Round #276 (Div. 2)C. Bits(构造法)

    这道题直接去构造答案即可. 对于l的二进制表示,从右到左一位一位的使其变为1,当不能再变了(再变l就大于r了)时,答案就是l. 这种方法既可以保证答案大于等于l且小于等于r,也可以保证二进制表示时的1 ...

  5. 2.mysql优化---增删改优化

    整理自互联网 补充知识点:操作数据语句优化的认识 通常情况下,当访问某张表的时候,读取者首先必须获取该表的锁,如果有写入操作到达,那么写入者一直等待读取者完成操作(查询开始之后就不能中断,因此允许读取 ...

  6. MySQL下分页查询数据

      -- 分页 -- 前两条 -- 启始位置从下标0开始,查询的是数据库中的第1条开始 -- 0:启始位置 2:一次性查询多少条 select * from account LIMIT 0,2; -- ...

  7. UGUI技巧

    http://www.cnblogs.com/suoluo/p/5427514.html Text中的可以单独指定某些文字的颜色,只需将想要变色的文本放在<color=**></co ...

  8. 【转】深入剖析Java中的装箱和拆箱

    深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱 ...

  9. java编程思想第八章多态

    前言: 封装:通过合并特征和行为创建新的数据类型. 实现隐藏:通过将细节“私有化”,把接口和实现分离. 多态:消除类型间的耦合关系.也称作动态绑定,后期绑定或运行时绑定. 8.1再论向上转型: 对象既 ...

  10. DIY ESXI虚拟化服务器再度升级ESXI6.0 (U盘安装Esxi)

    前期我写了一个篇关于<IT屌丝DIY ESXI虚拟化服务器记实 >链接地址:http://lidongni.blog.51cto.com/2554605/1643996,这次主要是在原有的 ...