Find the median

题目链接:

https://ac.nowcoder.com/acm/contest/887/E

题目描述

Let median of some array be the number which would stand in the middle of this array if it was sorted beforehand. If the array has even length let median be smallest of of two middle elements. For example, median of the array \([10,3,2,3,2]\) is 3 (i.e. \([2,2,\underline{3},3,10]\)). Median of the array [1,5,8,1] is 1 (i.e. \([1,\underline{1},5,8]\)).

At first, you're given an empty sequence. There are N operations. The i-th operation contains two integers \(L_i\) and \(R_i\). This means that adding \(R_i-L_i+1\) integers \(L_i, L_i+1, ... , R_i\) into the sequence. After each operation, you need to find the median of the sequence.

输入描述:

The first line of the input contains an integer \(N\ (1 \leq N \leq 400000)\) as described above.

The next two lines each contains six integers in the following format, respectively:

  • \(X_1\ X_2\ A_1\ B_1\ C_1\ M_1\)
  • \(Y_1\ Y_2\ A_2\ B_2\ C_2\ M_2\)

These values are used to generate \(L_i, R_i\) as follows:

We define:

  • \(X_i = (A_1 \times X_{i-1} + B_1 \times X_{i-2} + C_1)\ module\ M_1\), for \(i= 3\ to\ N\)
  • \(Y_i = (A_2 \times Y_{i-1} + B_2 \times Y_{i-2} + C_2)\ module\ M_2\), for \(i = 3\ to\ N\)

We also define:

  • \(L_i = min(X_i, Y_i) + 1\), for \(i = 1\ to\ N\).
  • \(R_i = max(X_i, Y_i) + 1\), for \(i = 1\ to\ N\).

Limits:

\(1 \leq N \leq 400000\)

\(0 \leq A_1 < M_1\)

\(0 \leq A_2 < M_2\)

\(0 \leq B_1 < M_1\)

\(0 \leq B_2 < M_2\)

\(0 \leq C_1 < M_1\)

\(0 \leq C_2 < M_2\)

\(0 \leq X_1 < M_1\)

\(0 \leq X_2 < M_1\)

\(0 \leq Y_1 < M_2\)

\(0 \leq Y_2 < M_2\)

\(1 \leq M_1 \leq 10^9\)

\(1 \leq M_2 \leq 10^9\)

输出描述:

You should output lines. Each line contains an integer means the median.

样例输入

5

3 1 4 1 5 9

2 7 1 8 2 9

样例输出

3

4

5

4

5

说明

L = [3, 2 ,4, 1, 7]

R = [4, 8, 8, 3, 9]

题意

给你一个空序列,\(n\)条指令,每次给你\(l,r\) ,表示向序列中加入\(l,l+1,\cdots,r\) 总共\(r-l+1\)个元素,每条指令后输入序列的中位数。

\(n\)条指令按题目所给的方法生成。

题解

这题如果不用离散的话,直接上权值线段树,这里着重讲一下离散的问题。

离散时我开始觉得很不能理解的地方:

  1. 什么时候左闭右开

  2. 什么时候右端点+1

  3. 什么时候右端点-1

我们不妨先来想一组数据:插入\((1,1) \ \ (1,5) \ \ (5,5)\)

如果按照普通离散是不是离散后就是\((1,1) \ \ (1,2) \ \ (2,2)\)

再用普通线段树,那么会发现\((1,1)+(2,2)\)和\((1,2)\)效果一样,也就是中间的点没了,为什么呢?

就是因为离散后我们没法判断某个点是左端点还是右端点还是中间点,导致两点间隙无法判断。

我的处理方法:

  1. 将离散的点连起来变成求线段长度,比如求\((1,5)\)改成求\((1,6)\)这条线段的长度\((\)都是\(5)\)
  2. 线段树每个节点\((l,r)\),实际管理区间是\((l,r+1)\)
  3. 加入线段时,记得右端-1,因为线段树会往右多管理一个点

这样\((1,1) \ \ (1,5) \ \ (5,5)\) 就变成了\((1,2)\ \ (1,6)\ \ (5,6)\),离散后再变成\((1,2)\ \ (1,4) \ \ (3,4)\),记得加入时右端点-1,即\((1,1)\ \ (1,3)\ \ (3,3)\)这几个区间权值+1。

\(ps:\) 这种区间覆盖问题很多都是要考虑端点的问题。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x7f7f7f7f
#define N 800050
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
ll n,num;
ll X[N],Y[N],kth[N];
struct Query{ll l,r;}que[N];
struct Tree{ll l,r,lazy,sum;}tr[N<<2];
void push_up(ll x)
{
ll len=kth[tr[x].r+1]-kth[tr[x].l];
if (tr[x].l==tr[x].r)tr[x].sum=0;
else tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
tr[x].sum+=tr[x].lazy*len;
}
void push_down(ll x)
{
Tree &a=tr[x<<1],&b=tr[x<<1|1];
a.lazy+=tr[x].lazy;
b.lazy+=tr[x].lazy;
tr[x].lazy=0;
push_up(x<<1);
push_up(x<<1|1);
}
void bt(ll x,ll l,ll r)
{
tr[x].lazy=tr[x].sum=0; tr[x].l=l; tr[x].r=r;
if (l==r)return;
ll mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
}
void change(ll x,ll l,ll r)
{
if (l<=tr[x].l&&tr[x].r<=r)
{tr[x].lazy++;push_up(x);return;}
ll mid=(tr[x].l+tr[x].r)>>1;
if (l<=mid)change(x<<1,l,r);
if (mid<r)change(x<<1|1,l,r);
push_up(x);
}
ll query(ll x,ll k)
{
if (tr[x].l==tr[x].r)return kth[tr[x].l]+(k-1)/tr[x].lazy;
push_down(x);
ll ls=tr[x<<1].sum;
if (ls<k)return query(x<<1|1,k-ls);
else return query(x<<1,k);
}
void work()
{
ll A1,B1,C1,A2,B2,C2,M1,M2,sum=0;
read(n);
read(X[1]); read(X[2]); read(A1); read(B1); read(C1); read(M1);
read(Y[1]); read(Y[2]); read(A2); read(B2); read(C2); read(M2);
for(ll i=3;i<=n;i++)X[i]=(A1*X[i-1]+B1*X[i-2]+C1)%M1;
for(ll i=3;i<=n;i++)Y[i]=(A2*Y[i-1]+B2*Y[i-2]+C2)%M2;
for(ll i=1;i<=n;i++)
{
que[i].l=min(X[i],Y[i])+1;
que[i].r=max(X[i],Y[i])+2;
kth[++num]=que[i].l;
kth[++num]=que[i].r;
}
sort(kth+1,kth+num+1);
num=unique(kth+1,kth+num+1)-kth-1;
bt(1,1,num);
for(ll i=1;i<=n;i++)
{
ll l=lower_bound(kth+1,kth+num+1,que[i].l)-kth;
ll r=lower_bound(kth+1,kth+num+1,que[i].r)-kth;
sum+=que[i].r-que[i].l;
change(1,l,r-1);
printf("%lld\n",query(1,(sum+1)/2));
} }
signed main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
work();
}

2019牛客多校第七场E Find the median 权值线段树+离散化的更多相关文章

  1. 2019牛客多校第七场E Find the median 离散化+线段树维护区间段

    Find the median 题意 刚开始集合为空,有n次操作,每次操作往集合里面插入[L[i],R[i]]的值,问每次操作后中位数是多少 分析 由于n比较大,并且数可以达到1e9,我们无法通过权值 ...

  2. 2019牛客多校第七场H Pair 数位DP

    题意:给你一个3个数A, B, C问有多少对pair(i, j),1 <= i <= A, 1 <= j <= B, i AND j > C或 i XOR j < ...

  3. 2019牛客多校第七场C-Governing sand(线段树+枚举)

    Governing sand 题目传送门 解题思路 枚举每一种高度作为最大高度,则需要的最小花费的钱是:砍掉所有比这个高度高的树的所有花费+砍掉比这个高度低的树里最便宜的m棵树的花费,m为高度低的里面 ...

  4. 2019牛客多校第七场 F Energy stones 树状数组+算贡献转化模拟

    Energy stones 题意 有n块石头,每块有初始能量E[i],每秒石头会增长能量L[i],石头的能量上限是C[i],现有m次时刻,每次会把[s[i],t[i]]的石头的能量吸干,问最后得到了多 ...

  5. 2019牛客多校第八场 F题 Flowers 计算几何+线段树

    2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...

  6. 牛客多校第七场 C Bit Compression 思维

    链接:https://www.nowcoder.com/acm/contest/145/C来源:牛客网 A binary string s of length N = 2n is given. You ...

  7. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  8. 2019牛客多校第四场 A meeting

    链接:https://ac.nowcoder.com/acm/contest/884/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...

  9. Find the median(2019年牛客多校第七场E题+左闭右开线段树)

    题目链接 传送门 题意 每次往集合里面添加一段连续区间的数,然后询问当前集合内的中位数. 思路 思路很好想,但是卡内存. 当时写的动态开点线段树没卡过去,赛后机房大佬用动态开点过了,\(tql\). ...

随机推荐

  1. confluence乱码问题

    1.上传附件需要统一字体,以测试通过:宋体字.雅黑.黑体 2.系统已做编码优化,支持windows字体.如下: 点击查看 3.之前文件有乱码,请重新上传 4.编辑一个 Office 附件文档的要求 当 ...

  2. prometheus简单监控Linux,mysql,nginx

    prometheus安装 下载安装 #官网下载 解压即可使用 https://prometheus.io/download/ #docker 方式安装 sudo docker run -n prome ...

  3. centos7下用kubeadm安装k8s集群并使用ipvs做高可用方案

    1.准备 1.1系统配置 在安装之前,需要先做如下准备.三台CentOS主机如下: 配置yum源(使用腾讯云的) 替换之前先备份旧配置 mv /etc/yum.repos.d/CentOS-Base. ...

  4. WebGL的shader

    WebGL的shader(着色器)有2种:vertexShader(定点着色器)和 fragmentShader(片段着色器) 顶点着色器:定义点的位置.大小 片元着色器:定义画出来的物体的材质(颜色 ...

  5. [linux]sudo 出现unable to resolve host 解决方法

    Ubuntu环境, 假设这台机器名字(hostname)叫abc, 每次执行sudo 就出现这个警告讯息:sudo: unable to resolve host abc虽然sudo 还是可以正常执行 ...

  6. CF1217C

    CF1217C 题意: 给定一个01串,一个good01串的定义是这个01串所代表的二进制数字刚好等于它的长度,允许前导零,问这个01串当中有几个good子串 解法: 枚举每一段连续的 $ 0 $ , ...

  7. Spring框架AOP

    aop技术是面向切面编程思想,作为OOP的延续思想添加到企业开发中,用于弥补OOP开发过程中的缺陷而提出的编程思想.AOP底层也是面向对象:只不过面向的不是普通的Object对象,而是特殊的AOP对象 ...

  8. ios编译库文件时出现的问题

    1. 警告:directory not found for option "xxxxxxxx" 文件路径未找到 选择工程, 编译的 (targets) 选择 Build Setti ...

  9. K-Means算法及代码实现

    1.K-Means算法 K-Means算法,也被称为K-平均或K-均值算法,是一种广泛使用的聚类算法.K-Means算法是聚焦于相似的无监督的算法,以距离作为数据对象间相似性度量的标准,即数据对象间的 ...

  10. react hook的todolist

    感觉好长时间没写博客一样,app.js代码 import React from 'react'; import { useState } from 'react'; function App() { ...