#A1482. 四元组

四元组

题目描述

有一个长度为 NN 的数列 A=(A0,,AN1)A=(A_0,\ldots,A_{N-1}),判断满足以下所有条件的整数四元组 (x,y,z,w)(x,y,z,w) 是否存在:

  • 0x<y<z<wN0\leq x < y < z < w \leq N
  • Ax+Ax+1++Ay1=PA_x+A_{x+1}+\cdots+A_{y-1} = P
  • Ay+Ay+1++Az1=QA_y+A_{y+1}+\cdots+A_{z-1}= Q
  • Az+Az+1++Aw1=RA_z+A_{z+1}+\cdots+A_{w-1}=R

名词解释:

NN 元组:NN 个有关联的元素,按照一定顺序组成的一个序列。

数据范围

  • 3N2×1053\le N \le 2 \times10^5
  • 1Ai1091\le A_i \le 10^9
  • 1P,Q,R10151 \le P,Q,R \le 10^{15}

输入格式

两行,第一行分别是 N,P,Q,RN,P,Q,R 四个整数,第二行是 NN 个数 AiA_i

N N P P Q Q R R

A0 A_0 A1 A_1 \ldots AN1 A_{N-1}

输出格式

如果满足条件的四元组存在,输出 Yes,否则输出 No

所以本题的测试数据捆绑了 subtask(必然的)。

样例 #1

样例输入 #1

10 5 7 5
1 3 2 2 2 3 1 4 3 2

样例输出 #1

Yes

样例 #2

样例输入 #2

9 100 101 100
31 41 59 26 53 58 97 93 23

样例输出 #2

No

样例 #3

样例输入 #3

7 1 1 1
1 1 1 1 1 1 1

样例输出 #3

Yes

提示

看数据范围:3N2×1053 \le N \le 2\times 10^5

暴力肯定会 TLE,所以肯定要优化。

优化思路1

本题要多次求区间和,因此肯定可以用 前缀和 优化。

  • 前缀和数组 s[i]=a[0]+a[1]+...+a[i-1]
  • 求出前缀和数组后,原数组的区间和 a[L]+a[L+1]+...+a[R] 就等于 s[R]-s[L-1]

优化思路2

把题中的条件改写成前缀和形式。以第一个条件为例:

Ax+Ax+1++Ay1=PA_x+A_{x+1}+\cdots+A_{y-1} = P

为了描述方便,规定 S0=0S_0=0, S1=A0S_1=A_0,以此类推,那么上面的式子就可以改写成

SySx=PSy=Sx+PS_y-S_x=P \rightarrow S_y=S_x+P

注意到 AiA_i 都是正整数,所以 SiS_i 是单调递增的,那么后续就可以采用 二分查找 来求解本题了。

其他几个条件如法炮制。

参考

  • 二分查找可以使用 STL 里的函数 binary_search。例:
int a[5]={11,22,33,44,55};
if(binary_search(a, a+5, 33))
    cout<<"存在33";
  • 也可以把所有的前缀和存入 set 中,使用 setfind 方法查找。例:
set<int> s;
s.insert(11); s.insert(22); s.insert(33);
if(s.find(22) != s.end())
    cout<<"存在22";

两种做法花费的时间都是 O(logn)O(\log n)