题面

有一个长度为

n

\tt n

n 的序列

a

\tt a

a ,对于每一个位置

i

[

1

,

n

]

\tt i\in[1,n]

i∈[1,n]:

  • 选择一个区间

    [

    l

    ,

    r

    ]

    \tt[l,r]

    [l,r] 满足

    1

    l

    i

    r

    n

    \tt1\leq l\leq i\leq r\leq n

    1≤l≤i≤r≤n 。

  • 把区间

    [

    l

    ,

    r

    ]

    \tt[l,r]

    [l,r] 中的数拿出来(很明显包括

    a

    i

    \tt a_i

    ai​) ,从小到大排序,值相同的可以随意排。

  • 中间位置定义为:

    {

    l

    e

    n

    g

    t

    h

    +

    1

    2

    ,

    (

    l

    e

    n

    g

    t

    h

    %

    2

    =

    1

    )

    l

    e

    n

    g

    t

    h

    2

    +

    1

    ,

    (

    l

    e

    n

    g

    t

    h

    %

    2

    =

    0

    )

    \left\{\begin{array}{cc}\frac{\tt length+1}{2}, & (\tt length\,\%\,2=1)\\\frac{\tt length}{2}+1, & (\tt length\,\%\,2=0)\end{array}\right.

    {2length+1​,2length​+1,​(length%2=1)(length%2=0)​,即

    l

    e

    n

    g

    t

    h

    +

    1

    2

    \tt\left\lceil\frac{length+1}{2}\right\rceil

    ⌈2length+1​⌉ 。

  • 位置

    i

    \tt i

    i 的奇怪度就是

    a

    i

    \tt|a_i排序后的位置-中间位置|

    ∣ai​排序后的位置−中间位置∣ 。

给出

n

\tt n

n 和序列

a

\tt a

a ,每个位置

i

\tt i

i 的所选区间

[

l

i

,

r

i

]

\tt[l_i,r_i]

[li​,ri​] 随意,但是你得输出位置

i

\tt i

i 的最大奇怪度。

1

n

200

000

,

1

a

i

n

\tt1\leq n\leq 200\,000~,~1\leq a_i\leq n

1≤n≤200000 , 1≤ai​≤n 。

题解

定义

S

1

\tt S_1

S1​ 为区间

[

l

,

r

]

\tt[l,r]

[l,r] 中严格小于

a

i

\tt a_i

ai​ 的元素个数,

S

2

\tt S_2

S2​ 为区间

[

l

,

r

]

\tt[l,r]

[l,r] 中等于

a

i

\tt a_i

ai​ 的元素个数(包括它自己),

S

3

\tt S_3

S3​ 为区间

[

l

,

r

]

\tt[l,r]

[l,r] 中严格大于

a

i

\tt a_i

ai​ 的元素个数,那么位置

i

\tt i

i 的奇怪度就是

max

{

(

S

1

+

S

2

)

(

S

1

+

S

2

)

+

S

3

+

1

2

S

1

+

(

S

2

+

S

3

)

+

1

2

(

S

1

+

1

)

\max\left\{\begin{matrix} \tt (S_1+S_2)-\left\lceil \frac{(S_1+S_2)+S_3+1}{2} \right\rceil\\ \tt \left\lceil \frac{S_1+(S_2+S_3)+1}{2} \right\rceil-(S_1+1) \end{matrix}\right.

max⎩⎨⎧​(S1​+S2​)−⌈2(S1​+S2​)+S3​+1​⌉⌈2S1​+(S2​+S3​)+1​⌉−(S1​+1)​

这里我都是忽略了绝对值符号的,因为第一行就是假设的

a

i

\tt a_i

ai​ 在中间位置后面,第二行假设的在前面。这两种情况对于与自己相同的元素利用不同,假设

a

i

\tt a_i

ai​ 在后面时,相同的尽量放前面(认为它们比

a

i

\tt a_i

ai​ 小),否则尽量放后面(认为它们比

a

i

\tt a_i

ai​ 大)。于是就有了上面的式子。

然后我们可以发现一个性质:同时在比

a

i

\tt a_i

ai​ 大的和比

a

i

\tt a_i

ai​ 小的数中各减去相同数量的元素后,答案不变。相当于把排序后的序列前后各掐掉等长的一段(不去掉

a

i

\tt a_i

ai​),此时中间位置和

a

i

\tt a_i

ai​ 的相对位置不变,奇怪度也不变,这个性质不难理解,看上面的式子也明白了。

那么说,对我们有用的信息就只有两者的差了!只要知道了差,然后假设较小者为

0

\tt0

0 ,再带入上述式子,得到的结果是一样的。

不妨认为与

a

i

\tt a_i

ai​ 相等的都小于它,接下来:

先考虑只求一个位置

i

\tt i

i 怎么做。我们把小于

a

i

\tt a_i

ai​ 的位置赋为

1

\tt1

1 ,大于它的位置赋为

1

\tt-1

−1 ,处理前缀和数组

s

u

m

\tt sum

sum ,那么就是求

s

u

m

r

s

u

m

l

1

\tt|sum_r-sum_{l-1}|

∣sumr​−suml−1​∣ 的最大值。此时,由于限定了

1

l

i

r

n

\tt1\leq l\leq i\leq r\leq n

1≤l≤i≤r≤n,我们在两者的范围内分别找最大或最小的

s

u

m

r

\tt sum_r

sumr​ 以及

s

u

m

l

1

\tt sum_{l-1}

suml−1​ 的值,就可以解决问题了。

如果是多个位置

i

\tt i

i 呢?按照值排序,建立主席树是一个办法,但是没有必要,这道题可是离线的。我们只需要从小到大计算,每次在一个线段树上维护

s

u

m

\tt sum

sum 数组和查询就行了。需要注意,值相同的位置要先全部修改,再挨个查询

假设与

a

i

\tt a_i

ai​ 相等的大于它也一样,就是值相同的位置要查询后再修改罢了。

时间复杂度

Θ

(

n

log

n

)

\tt \Theta(n\log n)

Θ(nlogn) 。

CODE

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define DB double
#define LL long long
#define ENDL putchar('\n')
#define lowbit(x) ((-x) & (x))
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
int a[MAXN];
vector<int> bu[MAXN];
int tre[MAXN<<2],tre2[MAXN<<2],lz[MAXN<<2],M;
void maketree(int n) {
M=1;while(M<n+2)M<<=1;
}
void addtree(int l,int r,int y) {
if(l > r) return ;
int s=M+l-1,t=M+r+1;
while(s || t) {
if(s<M) {
tre[s] = max(tre[s<<1],tre[s<<1|1])+lz[s];
tre2[s] = min(tre2[s<<1],tre2[s<<1|1])+lz[s];
}
if(t<M) {
tre[t] = max(tre[t<<1],tre[t<<1|1])+lz[t];
tre2[t] = min(tre2[t<<1],tre2[t<<1|1])+lz[t];
}
if((s>>1) ^ (t>>1)) {
if(!(s & 1)) tre[s^1] += y,tre2[s^1] += y,lz[s^1] += y;
if(t & 1) tre[t^1] += y,tre2[t^1] += y,lz[t^1] += y;
}
s >>= 1;t >>= 1;
}
return ;
}
int findmax(int l,int r) {
if(l > r) return -0x3f3f3f3f;
int s=M+l-1,t=M+r+1;
int ls = -0x3f3f3f3f,rs = -0x3f3f3f3f;
while(s || t) {
if(s<M) ls += lz[s];
if(t<M) rs += lz[t];
if((s>>1) ^ (t>>1)) {
if(!(s & 1)) ls = max(tre[s^1],ls);
if(t & 1) rs = max(tre[t^1],rs);
}
s >>= 1;t >>= 1;
}
return max(ls,rs);
}
int findmin(int l,int r) {
if(l > r) return 0x3f3f3f3f;
int s=M+l-1,t=M+r+1;
int ls = 0x3f3f3f3f,rs = 0x3f3f3f3f;
while(s || t) {
if(s<M) ls += lz[s];
if(t<M) rs += lz[t];
if((s>>1) ^ (t>>1)) {
if(!(s & 1)) ls = min(tre2[s^1],ls);
if(t & 1) rs = min(tre2[t^1],rs);
}
s >>= 1;t >>= 1;
}
return min(ls,rs);
}
int as[MAXN];
int main() {
n = read();
maketree(n);
for(int i = 1;i <= n;i ++) {
a[i] = read();
bu[a[i]].push_back(i);
addtree(i,n,-1);
}
for(int i = 1;i <= n;i ++) {
for(int j = 0;j <(int)bu[i].size();j ++) { // -1 -> 1
int y = bu[i][j];
int ll = max(0,findmax(1,y-1)),rr = findmin(y,n);
int mx = ll-rr;
as[y] = max(as[y],(mx+2)/2-1);
}
for(int j = 0;j <(int)bu[i].size();j ++) {
int y = bu[i][j];
addtree(y,n,2);
}
for(int j = 0;j <(int)bu[i].size();j ++) {
int y = bu[i][j];
int ll = min(0,findmin(1,y-1)),rr = findmax(y,n);
int mi = rr-ll;
as[y] = max(as[y],mi-(mi+2)/2);
}
}
for(int i = 1;i <= n;i ++) {
printf("%d ",as[i]);
}ENDL;
return 0;
}

[CF1539F] Strange Array (线段树)的更多相关文章

  1. CF1539F Strange Array

    这玩意为啥是紫. 考虑对每个小于\(x\)的数值设为1,大于\(x\)的数值设为-1. 那么对于答案要求的就是绝对值最大的连续段. 线段树是很显然的. 考虑我们不能对每个数都进行一遍重构,这样就退化到 ...

  2. [Codeforces 266E]More Queries to Array...(线段树+二项式定理)

    [Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...

  3. 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法

    C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...

  4. codeforces 719E E. Sasha and Array(线段树)

    题目链接: E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input sta ...

  5. Codeforces 482B Interesting Array(线段树)

    题目链接:Codeforces 482B Interesting Array 题目大意:给定一个长度为N的数组,如今有M个限制,每一个限制有l,r,q,表示从a[l]~a[r]取且后的数一定为q,问是 ...

  6. Codeforces 1114F Please, another Queries on Array? 线段树

    Please, another Queries on Array? 利用欧拉函数的计算方法, 用线段树搞一搞就好啦. #include<bits/stdc++.h> #define LL ...

  7. 2019ccpc网络赛hdu6703 array(线段树)

    array 题目传送门 解题思路 操作1是把第pos个位置上的数加上\(10^7\),操作2是找到区间[1,r]中没有且大于k的最小的数.注意到k的范围是小于等于n的,且n的范围是\(10^5\),远 ...

  8. Codeforces Round #275 Div.1 B Interesting Array --线段树

    题意: 构造一个序列,满足m个形如:[l,r,c] 的条件. [l,r,c]表示[l,r]中的元素按位与(&)的和为c. 解法: 线段树维护,sum[rt]表示要满足到现在为止的条件时该子树的 ...

  9. 暑假集训单切赛第一场 CF 266E More Queries to Array(线段树+二项式展开式)

    比赛时,第二题就是做的这个,当时果断没仔细考虑,直接用线段树暴力求.结果易想而知,超时了. 比赛后搜了搜题解,恍然大悟. 思路:显然用线段树,但是由于每次查询都会有变,所以不可能存储题目中的式子.   ...

  10. Codeforces295A - Greg and Array(线段树的成段更新)

    题目大意 给定一个序列a[1],a[2]--a[n] 接下来给出m种操作,每种操作是以下形式的: l r d 表示把区间[l,r]内的每一个数都加上一个值d 之后有k个操作,每个操作是以下形式的: x ...

随机推荐

  1. 互联网公司目标管理OKR和绩效考核的误区

    最近看了一篇关于「谷歌放弃OKR,转向全新的GRAD系统」的文章,我转到了研发效能DevOps的微信群里,结果引起了大家热烈的讨论,正好我们也在使用 OKR,所以也来谈谈我的理解以及我们应用起来的实际 ...

  2. ASP.NET Core 应用配置指定地址和端口

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年5月10日. 几种方式 ASP.NET Core 应用配置指定地址和端口支持以下几种主要方式: 1.在命令行模式启动应用时设置 --u ...

  3. Ubuntu 配置 .NET 使用环境

    本文迁移自Panda666原博客,原发布时间:2021年3月29日. 说明 测试使用的环境 Linux版本:Ubuntu Server 20.04 LTS x64 .NET SDK版本:5.0 其他版 ...

  4. C# 使用SpecFlow创建BDD测试用例

    将自然语言编写的测试用例转换为可执行的测试,可以大大降低需求与开发之间的沟通成本,这是BDD(行为驱动开发)希望达到的效果.SpecFlow是.Net平台的BDD工具,可以帮助我们创建面向BDD的测试 ...

  5. Git镜像

    http://npm.taobao.org/mirrors/git-for-windows/v2.34.1.windows.1/ Git 阿里镜像,高速 下载

  6. 我的开源之路:耗时 6 个月发布线程池框架,GitHub 1.7k Star!

    文章首发在公众号(龙台的技术笔记),之后同步到掘金和个人网站:xiaomage.info Hippo4J 线程池框架经过 6 个多月的版本迭代,2022 年春节当天成功发行了 1.0.0 RELEAS ...

  7. MySQL-1-概念

    数据库相关概念 DB:数据库(database):存储数据的"仓库".它保存了一系列有组织的数据 DBMS:数据库管理系统,又称为数据库软件(产品),用于管理DB中的数据 SQL: ...

  8. Java开发学习(六)----DI依赖注入之setter及构造器注入解析

    一.DI依赖注入 首先来介绍下Spring中有哪些注入方式? 我们先来思考 向一个类中传递数据的方式有几种? 普通方法(set方法) 构造方法 依赖注入描述了在容器中建立bean与bean之间的依赖关 ...

  9. Django【查询】 基础回顾与深入应用

    官方Django3.2 文档:https://docs.djangoproject.com/en/3.2/topics/db/queries/ 本文大部分内容参考官方3.2版本文档撰写,仅供学习使用 ...

  10. .net MVC微信开发自定义View类型菜单时在相应控制器获取用户OpenID的问题

    因为公司的项目在接收微信服务器Post过来的数据包是有指定的入口,所以在相应控制器里无法接收到微信服务器Post过来的数据,所以无法获得OpenID,也尝试过先在入口哪里解析获得OpenID再通过Se ...