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. OpenCV2.4.5 加 Cuda5.0在vs2010下工

    想用opencv结合gpu加速处理,想重新编译opencv结合cuda模块无奈总出错 在国外网站上搜到一个cmakelists比较靠谱,项目可以生成,但还没有测试程序把list贴出来 ######## ...

  2. 一台服务器配置多个mysql实例

    在公司资源紧张的情况下,需要在一台服务器上部署多个数据库实例,现在就来实战一下该情况. 需要启动两个不同的端口,分别是3306和3307 [root@node1 ~]# mkdir /u01/mysq ...

  3. JAVA基础知识|TCP/IP协议

    虽然写代码也有一定的年头了,但是对于一些基础概念,还是很模糊.这在后来的学习过程中,带来了很大的痛苦,所以痛定思痛,决心重新学习这些概念.并把自己的理解和查询的资料做一些整合,便于以后查阅! 一.什么 ...

  4. nginx 配置 nodejs 反向代理

    upstream my_nodejs_upstream { server ; keepalive ; } server { listen ; server_name www.my-website.co ...

  5. Windows使用Vagrant&VirtualBox搭建虚拟开发环境

    Vagrant 是一款用来构建虚拟开发环境的工具 , 我们可以通过 Vagrant 封装一个 Linux 的开发环境 , 分发给团队成员 ; 成员可以在自己喜欢的桌面系统 Mac/Windows/Li ...

  6. 《你不知道的JavaScript(上)》笔记——作用域闭包

    当函数可以记住并访问所在的词法作用域时, 就产生了闭包, 即使函数是在当前词法作用域之外执行. function wait(message) { setTimeout( function timer( ...

  7. JAVA通过FTP方式向远程服务器或者客户端上传、下载文件,以及删除FTP服务器上的文件

    1.在目标服务器上搭建FTP服务器 搭建方式有多种大家可以自行选择,例如使用Serv-U或者FTPServer.exe:这里我以FTPServer.exe为例搭建:在目标服务器(这里对应的IP是10. ...

  8. Connection

    作用: * 获取执行sql语句对象 ** createStatement(): 获取Statement对象 ** prepareStatement(String sql): 获取预处理对象 ** pr ...

  9. [Java读书笔记] Effective Java(Third Edition) 第 5 章 泛型

    第 26 条:请不要使用原生态类型 声明中具有一个或多个类型参数的类或者接口,就是泛型(generic). 例如List接口只有单个类型参数E, 表示列表的元素类型.这个接口全称List<E&g ...

  10. List的remove方法里的坑

    今天遇到一件怪事,用一个ArrayList添加了一个对象,再调用ArrayList的remove方法删除该对象,当然这时对象是数据库里查出来的,但内容绝对是一样,却发现remove失败了.演示一下,这 ...