2653: middle

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2381  Solved: 1340
[Submit][Status][Discuss]

Description

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

Input

第一行序列长度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
 

Output

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

Sample Input

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

Sample Output

271451044
271451044
969056313

HINT

 

Source

 

[Submit][Status][Discuss]

HOME Back

clj dalao出的神题%%%

一道很好的思维题吧。首先可以发现,满足条件的中位数是具有二分性(即单调性)的。比如数列中一个数$x$,我们把所有比$x$小的数的位置标记成-1,比$x$大的数的位置标记成1,如果和大于0,表示比它大的数枚举多了,所以把答案往右移,反之往左移。满足二分性,所以二分check时满足区间最大值>=0就表示这个数可以作为答案,更新答案。(<=0也可以用来判断,不过维护的是最小值即可)

可以发现,问题中的$bc$区间一定被包括,所以查询$ab$的右缀连续区间最大值和$cd$的左缀连续区间最大值以及$bc$的整个区间和即可。【注意】所有区间都是左闭右开。

考虑如何维护。给每个值建一棵主席数,预处理出每棵主席数上-1和1的情况,每次就在对应二分的pos的主席树上查询即可。

最后是合并节点的问题,$lmax$是从左儿子的$lmax$或者左儿子的$sum$加右儿子的$lmax$更新过来,$rmax$同理。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; int n, ans, a, b, c, d, q[]; struct QwQ {
int v, id;
} A[];
bool cmp ( QwQ a, QwQ b ) { return a.v < b.v; } struct node {
node *ls, *rs;
int sum, lmax, rmax;
void update ( ) {
sum = ls -> sum + rs -> sum;
lmax = max ( ls -> lmax, ls -> sum + rs -> lmax );
rmax = max ( rs -> rmax, rs -> sum + ls -> rmax );
}
} *zero, *root[], pool[*], *tail = pool; node *newnode ( ) {
node *nd = ++ tail;
nd -> ls = zero; nd -> rs = zero;
nd -> sum = ; nd -> lmax = ; nd -> rmax = ;
return nd;
} node *build ( int l, int r ) {
node *nd = newnode ( );
if ( l == r ) {
nd -> sum = nd -> lmax = nd -> rmax = ;
return nd;
}
int mid = ( l + r ) >> ;
nd -> ls = build ( l, mid );
nd -> rs = build ( mid + , r );
nd -> update ( );
return nd;
} void init ( ) {
zero = ++ tail;
zero -> ls = zero; zero -> rs = zero; zero -> sum = ;
zero -> lmax = ; zero -> rmax = ;
root[] = build ( , n );
} node *insert ( node *nd, int l, int r, int pos ) {
node *nnd = newnode ( );
if ( l == r ) { nnd -> sum = -; nnd -> lmax = nnd -> rmax = -; return nnd; }
int mid = ( l + r ) >> ;
if ( mid >= pos ) {
nnd -> rs = nd -> rs;
nnd -> ls = insert ( nd -> ls, l, mid, pos );
} else {
nnd -> ls = nd -> ls;
nnd -> rs = insert ( nd -> rs, mid + , r, pos );
}
nnd -> update ( );
return nnd;
} int query_s ( node *nd, int l, int r, int L, int R ) {
if ( L > R ) return ;
if ( l >= L && r <= R ) return nd -> sum;
int mid = ( l + r ) >> , ans = ;
if ( L <= mid ) ans += query_s ( nd -> ls, l, mid, L, R );
if ( R > mid ) ans += query_s ( nd -> rs, mid + , r, L, R );
return ans;
} int query_l ( node *nd, int l, int r, int L, int R ) {
if ( L > R ) return ;
if ( l >= L && r <= R ) return nd -> lmax;
int mid = ( l + r ) >> , ans = ;
if ( L <= mid ) ans = max ( ans, query_l ( nd -> ls, l, mid, L, R ) );
if ( R > mid ) {
int lsum = query_s ( nd -> ls, l, mid, L, mid );
int rmaxl = query_l ( nd -> rs, mid + , r, L, R );
ans = max ( ans, lsum + rmaxl );
}
return ans;
} int query_r ( node *nd, int l, int r, int L, int R ) {
if ( L > R ) return ;
if ( l >= L && r <= R ) return nd -> rmax;
int mid = ( l + r ) >> , ans = ;
if ( R > mid ) ans = max ( ans, query_r ( nd -> rs, mid + , r, L, R ) );
if ( L <= mid ) {
int rsum = query_s ( nd -> rs, mid + , r, mid + , R );
int lmaxr = query_r ( nd -> ls, l, mid, L, R );
ans = max ( ans, rsum + lmaxr );
}
return ans;
} bool check ( int pos ) {
int ab = query_r ( root[pos], , n, a, b - );
int cd = query_l ( root[pos], , n, c + , d );
int bc = query_s ( root[pos], , n, b, c );
if ( ab + cd + bc >= ) return ;
return ;
} int find ( ) {
int l = , r = n, ans = ;
while ( l <= r ) {
int mid = ( l + r ) >> ;
if ( check ( mid ) ) {
ans = mid; l = mid + ;
} else r = mid - ;
}
return ans;
} int main ( ) {
scanf ( "%d", &n );
init ( );
for ( int i = ; i <= n; i ++ ) {
scanf ( "%d", &A[i].v ); A[i].id = i;
}
sort ( A + , A + + n, cmp );
for ( int i = ; i <= n; i ++ )
root[i] = insert ( root[i-], , n, A[i-].id );
int Q;
scanf ( "%d", &Q );
while ( Q -- ) {
for ( int i = ; i <= ; i ++ ) {
int x; scanf ( "%d", &x );
q[i] = ( x + ans ) % n + ;
}
sort ( q + , q + );
a = q[], b = q[], c = q[], d = q[];
ans = A[find ( )].v;
printf ( "%d\n", ans );
}
return ;
}

【BZOJ】2653: middle的更多相关文章

  1. 【BZOJ】3052: [wc2013]糖果公园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...

  2. 【BZOJ】3319: 黑白树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...

  3. 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...

  4. 【BZOJ】1013: [JSOI2008]球形空间产生器sphere

    [BZOJ]1013: [JSOI2008]球形空间产生器sphere 题意:给n+1个n维的点的坐标,要你求出一个到这n+1个点距离相等的点的坐标: 思路:高斯消元即第i个点和第i+1个点处理出一个 ...

  5. 【BZOJ】1002:轮状病毒(基尔霍夫矩阵【附公式推导】或打表)

    Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图 ...

  6. 【BZOJ】【3083】遥远的国度

    树链剖分/dfs序 其实过了[BZOJ][4034][HAOI2015]T2以后就好搞了…… 链修改+子树查询+换根 其实静态树的换根直接树链剖分就可以搞了…… 因为其实只有一样变了:子树 如果roo ...

  7. 【BZOJ】【2434】【NOI2011】阿狸的打字机

    AC自动机+DFS序+BIT 好题啊……orz PoPoQQQ 大爷 一道相似的题目:[BZOJ][3172][TJOI2013]单词 那道题也是在fail树上数有多少个点,只不过这题是在x的fail ...

  8. 【BZOJ】【2738】&【Tsinsen】【A1333】矩阵乘法

    整体二分+树状数组 过了[BZOJ][2527][POI2011]Meteors以后这题就没那么难啦~ 关键是[从小到大]依次插入数字,然后整体二分每个查询的第k大是在第几次插入中被插入的……嗯大概就 ...

  9. 【BZOJ】【3170】【TJOI2103】松鼠聚会

    切比雪夫距离+曼哈顿距离 题解:http://www.cnblogs.com/zyfzyf/p/4105456.html 其实应该先做这题再做[BZOJ][3210]花神的浇花集会的吧…… 我们发现d ...

随机推荐

  1. APP爬虫之Appium使用

    一.安装环境 Appium安装(windows版) 一.安装node.js 1.到官网下载node.js:https://nodejs.org/en/download/ 2.获取到安装文件后,直接双击 ...

  2. JS设计模式——4.继承(概念)

    类式继承 0.构造函数 一个简单的Person类 function Person(name){ this.name = name; } Person.prototype.getName = funct ...

  3. vsftpd 安装配置详细教程

    linux下ftp软件不少,大致特点:<br /> wu-ftp:比较老牌,但针对它的攻击比较多,设置比较麻烦,但功能比较强大.<br /> vsftpd:功能强大,配置也比较 ...

  4. [MySQL] AUTO_INCREMENT lock Handing in InnoDB

    MySQL AUTO_INCREMENT lock Handing in InnoDB 在MySQL的表设计中很普遍的使用自增长字段作为表主键, 实际生产中我们也是这样约束业务开发同学的, 其中的优势 ...

  5. 转:PHP环境搭建 - Linux

    本文PHP环境采用,nginx + PHP7 + mysql 5.6 一.安装mysql 5.6 参见:http://www.cnblogs.com/rslai/p/7853465.html 二.Ng ...

  6. Linux 基础——文件搜索命令find

    一.find命令的好处 有时会经常在目录下找文件或目录的具体存放在哪,但是该目录下的文件又很多不好找出.这时并不需要手动查看所有的文件,用find命令来帮助查找就行了.所以文件或目录一定归好类,存放有 ...

  7. Nginx 虚拟目录和虚拟主机的配置

    nginx.conf 配置文件的几个常用命令 nginx 配置文件主要分为六个区域: main: 全局设置 events: nginx工作模式 http: http设置 sever: 主机设置 loc ...

  8. 简易web-slide

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 安装requests

    requests包让Python程序能够轻松地向网站请求信息以及检查返回的响应.要安装requests,请执行类似于下面的命令: $ pip3 install --user requests http ...

  10. 语言模型srilm基本用法

    目录: 一基本训练 二语言模型打分 三语言模型剪枝 四语言模型合并 五语言模型使用词典限制 一.基本训练 #功能 读取分词后的text文件或者count文件,然后用来输出最后汇总的count文件或者语 ...