【单调栈】RP俱乐部

【问题描述】
最近小 R 成立了一个 RP 俱乐部, 吸引了很多热心的同学。 成为这个俱乐部会
员的唯一条件就是要和老会员进行一场比赛, 以证明自己的 RP。
我们假设每个人都有一个固定的 RP 值, 另外, 每个人都有一个唯一的 ID。 为了使
比赛更加好看, 每一个新会员都会选择与他的 RP 最为接近的人比赛, 即双方的 RP 值
之差越小越好, 如果有两个人的 RP 值与他差别相同, 则他会选择更小的那一个人比赛。
现在, 给出所有会员的注册顺序, 你能帮小 R 统计每场比赛双方的 ID
吗?
【输入格式】
第一行一个数 N, 表示俱乐部新来的会员数(不包括小 R)。
以后 N 行每行两个正整数, 按照注册的顺序给出每个人的 ID 和 RP。
一开始小 R 就算是会员, ID 为 1, RP 为 1,000,000,000。 输入保证任意两个人的 RP
都不同。
【输出格式】
N 行, 每行两个数, 为每场比赛双方的 ID, 新会员的 ID 写在前面。
【样例】
club.in club.out
3
2 1
3 3
4 2
club.out
2 1
3 2
4 2
【数据规模】
40%的数据满足: N≤1,000 ID, RP≤1,000,000,000;
100%的数据满足: N≤200,000 ID, RP≤1,000,000,000。

如何快速求出对于每个会员来说RP最接近他且进入俱乐部的时间比他早的会员?

先把所有人按照RP排序,再分别从左到右、从右到左维护进入俱乐部时间从小到大的单调栈,就可以得到符合上述条件的会员。

至于这道题为什么可以用单调栈以后再补……

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 struct P{int realid,id,rp,ans;}p[200002];
 6 int a,n,top,sta[200002],trp[200002],real[200002];
 7 inline void read(int &x)
 8 {
 9     char ls=getchar();x=0;
10     for (;ls<‘0‘||ls>‘9‘;ls=getchar());
11     for (;ls>=‘0‘&&ls<=‘9‘;ls=getchar())x=x*10+ls-‘0‘;
12 }
13 bool cmp1(P a,P b)
14 {
15     return a.rp<b.rp;
16 }
17 bool cmp2(P a,P b)
18 {
19     return a.id<b.id;
20 }
21 int main()
22 {
23     memset(trp,0x7f,sizeof(trp));
24     scanf("%d",&n);
25     p[1].id=1;p[1].rp=1000000000;
26     real[1]=1;
27     for (int i=2;i<=n+1;i++)
28     {
29         p[i].id=i;
30         read(a),read(p[i].rp);
31         real[i]=a;
32     }
33     sort(p+1,p+n+2,cmp1);
34     top=-1;
35     for (int i=1;i<=n;i++)
36     {
37         while (top>=0&&p[sta[top]].id>p[i].id) top--;
38         if (top>=0)
39         {
40             trp[i]=abs(p[sta[top]].rp-p[i].rp);
41             p[i].ans=sta[top];
42         }
43         sta[++top]=i;
44     }
45     top=0;sta[0]=n+1;
46     for (int i=n;i>=1;i--)
47     {
48         while (top>=0&&p[sta[top]].id>p[i].id) top--;
49         if (abs(p[sta[top]].rp-p[i].rp)<trp[i])
50             p[i].ans=sta[top];
51         sta[++top]=i;
52     }
53     for (int i=1;i<=n;i++) p[i].ans=p[p[i].ans].id;
54     sort(p+1,p+n+1,cmp2);
55     for (int i=1;i<=n;i++)
56         printf("%d %d\n",real[i+1],real[p[i].ans]);
57 }
时间: 2024-11-02 10:02:51

【单调栈】RP俱乐部的相关文章

【bzoj3956】Count 单调栈+可持久化线段树

题目描述 输入 输出 样例输入 3 2 0 2 1 2 1 1 1 3 样例输出 0 3 题解 单调栈+可持久化线段树 本题是 bzoj4826 的弱化版(我为什么做题总喜欢先挑难的做QAQ) $k$对点对$(i,j)$有贡献,当且仅当$a_k=max(a_{i+1},a_{i+2},...,a_{r-1})$,且$a_k<a_i\&\&a_k<a_j$. 那么我们可以使用单调栈求出i左面第一个比它大的位置$lp[i]$,和右面第一个比它大的位置$rp[i]$,那么点对$(lp

【DP/单调栈】关于单调栈的一些题目(codevs 1159,codevs 2673)

题目描述 Description 这个月的pku月赛某陈没有参加,因为当时学校在考试[某陈经常逃课,但某陈还没有强大到考试也可以逃掉的程度].何况,对于北大校赛,水牛通常是没有什么希望考得好的[事实上某陈最好成绩是仅A了一道题]. 某陈郁闷.接下来他又将沉浸在无穷尽的刷题中,每天面对各种颜色的Status--WA,TLE,RE,甚至还有MLE,CE,PE什么什么的,他无比期待蓝色的AC. 话说RP爆发的某陈弄到了很久以后某次pku月赛的某题的题目和输入数据,如下所示. 输入数据包括n个测试点,每

【bzoj3238】[Ahoi2013]差异 后缀数组+单调栈

题目描述 输入 一行,一个字符串S 输出 一行,一个整数,表示所求值 样例输入 cacao 样例输出 54 题解 后缀数组+单调栈,几乎同 bzoj3879 的后半部分. 我明显是做题做反了... 这里还是说一下这道题的做法. 先用后缀数组求出height. 然后由于有LCP(a,c)=min(LCP(a,b),LCP(b,c))(rank[a]<rank[b]<rank[c]),所以我们只需要知道排名相邻的两个后缀的LCP,而这就是height数组的定义. 转化为子问题:给出n个数,求所有子

【bzoj5089】最大连续子段和 分块+单调栈

题目描述 给出一个长度为 n 的序列,要求支持如下两种操作: A  l  r  x :将 [l,r] 区间内的所有数加上 x : Q  l  r : 询问 [l,r] 区间的最大连续子段和. 其中,一个区间的最大连续子段和指的是:该区间所有子区间的区间和中的最大值(本题中子区间包括空区间,区间和为 0 ). 输入 第一行两个整数 n.m,表示序列的长度以及操作的数目. 之后的 m 行,每行输入一个操作,含义如题目所述.保证操作为  A  l  r  x  或  Q  l  r  之一. 对于 3

【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改

题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i个元素的值.接下来q行,每行包含两个整数l和r,代表一次询问. 输出 对于每次询问,输出一行,代表询问的答案. 样例输入 5 5 5 2 4 1 3 1 5 1 3 2 4 3 5 2 5 样例输出 28 17 11 11 17 题解 单调栈+离线+扫描线+树状数组区间修改 首先把使用单调栈找出每个

[bzoj4540][Hnoi2016]序列——单调栈+莫队+RMQ

题目大意: 给定一个序列,每次询问一个区间[L,R]所有子区间的最小值之和. 思路: 考虑莫队如何转移,新增一个端点R,则增加的区间为[L...R-1,R],考虑这些区间新贡献的最小值. 我们把从R开始向左单调下降的序列给求出来,不难发现最小值是由区间内包含的最靠左一个在单调下降序列里的元素的值所决定的. 于是我们利用单调栈求出每一个元素前面第一个小于它的元素\(pre_i\),并求出以这个元素结尾的所有区间的最小值的和\(f_i\),不难发现\(f_i=f_{pre_i}+(i-pre_i)\

[CSP-S模拟测试]:array(单调栈)

题目描述 在放完棋子之后,$dirty$又开始了新的游戏. 现在他拥有一个长为$n$的数组$A$,他定义第$i$个位置的分值为$i−k+1$,其中$k$需要满足: 对于任意满足$k\leqslant j\leqslant i$的$j$,有$A[k]\leqslant A[j]\leqslant A[i]$.当对于第$i$个数,有多个$k$满足条件时,取能获得较大分值的$k$. 现在,$dirty$想要知道$A$数组中分值最大的位置对应的分值为多少. 输入格式 第一行一个整数$n$,表示$A$数组

(单调栈)poj-2559 Largest Rectangle in a Histogram

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the

【单调栈】hdu1506 Largest Rectangle in a Histogram

单调栈的介绍及一些基本性质 http://blog.csdn.net/liujian20150808/article/details/50752861 依次把矩形塞进单调栈,保持其单增,矩形中的元素是一个三元组,存储其位置,高度,以及以其为高度的情况下,大矩形的左边界最多扩展到哪里. 每次将新的元素塞进栈的时候,其左边界就是其左侧第一个小于它的矩形的位置+1. 然后,每个矩形出栈的时候,记录其右边界为当前往栈里面塞的矩形的位置-1,然后更新答案即可. 注意最后把所有的矩形出栈,更新答案. #in