3509: [CodeChef] COUNTARI

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 883  Solved: 250
[Submit][Status][Discuss]

Description

给定一个长度为N的数组A[],求有多少对i, j, k(1<=i<j<k<=N)满足A[k]-A[j]=A[j]-A[i]。

Input

第一行一个整数N(N<=10^5)。
接下来一行N个数A[i](A[i]<=30000)。

Output

一行一个整数。

Sample Input

10
3 5 3 6 3 4 10 4 5 2

Sample Output

9

HINT

Source

分析:

考虑枚举中间项$a[j]$,我们可以使用$FFT$快速计算$ik$的配对个数,但是这样显然是$O(Nmaxnumlgmaxnum)$的,还没有暴力跑的快...

所以可以考虑分块,对于$ijk$都在同一块内或者$ij$在一块或者$jk$在一块的情况我们预处理出来,这些的复杂度是$O(len*N)$的,然后$ik$位于和$j$不同快的情况我们用$FFT$来计算,这个的复杂度是$O(\frac {N}{len}*maxnumlgmaxnum)$的...

如此计算,块的大小大概开到3000~2000就可以过去了...

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std; const int maxn=100000+5,maxblock=50+5;
const double pi=acos(-1); int n,N,m,L,blo,a[maxn],R[maxn],id[maxn],be[maxblock],en[maxblock],cnt[maxblock][maxn];
long long ans; struct complex{ double r,i; inline complex(double a=0,double b=0): r(a),i(b) {}; inline complex operator + (const complex &a){
return complex(r+a.r,i+a.i);
} inline complex operator - (const complex &a){
return complex(r-a.r,i-a.i);
} inline complex operator * (const complex &a){
return complex(r*a.r-i*a.i,r*a.i+i*a.r);
} }l[maxn],s[maxn]; inline void FFT(complex *l,int f){
for(int i=0;i<N;i++)
if(i>R[i]) swap(l[i],l[R[i]]);
for(int i=1;i<N;i<<=1){
complex wn(cos(pi/i),f*sin(pi/i));
for(int j=0;j<N;j+=i<<1){
complex w(1,0);
for(int k=0;k<i;k++,w=w*wn){
complex x=l[j+k],y=l[j+k+i]*w;
l[j+k]=x+y;
l[j+k+i]=x-y;
}
}
}
if(f==-1)
for(int i=0;i<N;i++)
l[i].r/=N;
} signed main(void){
// freopen("countari.in","r",stdin);
// freopen("countari.out","w",stdout);
scanf("%d",&n);
L=0;ans=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(N=1;N<=60000;N<<=1) L++;
for(int i=0;i<N;i++)
R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
blo=min(int(sqrt(n)*10),n);
for(int i=1;i<=n;i++) id[i]=(i-1)/blo+1;
for(int i=1;i<=id[n];i++)
be[i]=lower_bound(id+1,id+n+1,i)-id,
en[i]=upper_bound(id+1,id+n+1,i)-id-1;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++) cnt[id[i]][a[i]]++;
for(int B=1;B<=id[n];B++){
for(int i=be[B];i<=en[B];i++){
cnt[B][a[i]]--;
for(int j=be[B];j<i;j++)
if(2*a[i]-a[j]>=0) ans+=cnt[B][2*a[i]-a[j]];
}
}
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++) cnt[0][a[i]]++;
for(int B=1;B<=id[n];B++){
for(int i=be[B];i<=en[B];i++) cnt[0][a[i]]--;
for(int i=be[B];i<=en[B];i++){
for(int j=be[B];j<i;j++)
if(2*a[i]-a[j]>=0) ans+=cnt[0][2*a[i]-a[j]];
}
}
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++) cnt[0][a[i]]++;
for(int B=id[n];B>=1;B--){
for(int i=be[B];i<=en[B];i++) cnt[0][a[i]]--;
for(int i=be[B];i<=en[B];i++){
for(int j=i-1;j>=be[B];j--)
if(2*a[j]-a[i]>=0) ans+=cnt[0][2*a[j]-a[i]];
}
}
for(int B=1;B<=id[n];B++){
for(int i=0;i<N;i++) l[i].r=l[i].i=s[i].r=s[i].i=0;
for(int i=1;i<be[B];i++) l[a[i]].r++;
for(int i=en[B]+1;i<=n;i++) s[a[i]].r++;
FFT(l,1);FFT(s,1);
for(int i=0;i<N;i++) l[i]=l[i]*s[i];
FFT(l,-1);
for(int i=be[B];i<=en[B];i++) ans+=int(l[a[i]*2].r+0.5);
}
printf("%lld\n",ans);
return 0;
}

  


By NeighThorn

BZOJ 3509: [CodeChef] COUNTARI的更多相关文章

  1. [BZOJ 3509] [CodeChef] COUNTARI (FFT+分块)

    [BZOJ 3509] [CodeChef] COUNTARI (FFT+分块) 题面 给出一个长度为n的数组,问有多少三元组\((i,j,k)\)满足\(i<j<k,a_j-a_i=a_ ...

  2. bzoj 3509: [CodeChef] COUNTARI] [分块 生成函数]

    3509: [CodeChef] COUNTARI 题意:统计满足\(i<j<k, 2*a[j] = a[i] + a[k]\)的个数 \(2*a[j]\)不太好处理,暴力fft不如直接暴 ...

  3. BZOJ 3509 [CodeChef] COUNTARI ——分块 FFT

    分块大法好. 块内暴力,块外FFT. 弃疗了,抄SX队长$silvernebula$的代码 #include <map> #include <cmath> #include & ...

  4. BZOJ3509: [CodeChef] COUNTARI

    3509: [CodeChef] COUNTARI Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 85[Submit][St ...

  5. bzoj 4546: codechef XRQRS [可持久化Trie]

    4546: codechef XRQRS 可持久化Trie codechef上过了,bzoj上蜜汁re,看别人说要开5.2e5才行. #include <iostream> #includ ...

  6. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

  7. BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

    从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献 ...

  8. BZOJ 4260: Codechef REBXOR( trie )

    求出前缀和, 那么以第x个元素结尾的最大异或值是max(sumx^sump)(1≤p<x), 用trie加速. 后缀同理, 然后扫一遍就OK了.时间复杂度O(31N) ------------- ...

  9. BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1312  Solved: 501 ...

随机推荐

  1. vue框架初学习的基本指令

           学习地址:<ahref="https: cn.vuejs.="" org="" "="" targe ...

  2. C++ 无限定名称查找

    无限定名称查找 (关键字:懒惰,挑捡,using指令的特殊性) 无限定名称查找实际上就是指没有限定(名称空间和名称空间运算符)名存在的一个名字的出现,其中对于using指令,其内部包含的所有的声明是被 ...

  3. SummerVocation_Learning--java的自动打包与解包

    Auto Boxing: 自动将基础类型转换成对象(JDK1.5之后支持) Auto UnBoxing:自动将对象转换成基础类型 如 Map中的put方法,如果要传入键值对<a,1>,&l ...

  4. JZ2440开发板与ubuntu互ping,然后进行文件的共享和挂载

    操作手册如下:但本人直接用网线直接连通开发板的网口与电脑的网口没有成功过.采用路由器可以直接ping通,具体操作如下: 首先用网线将开发板和路由器连接.电脑无论是用wifi还是网线均可.然后关闭Win ...

  5. Django2.1集成xadmin管理后台所遇到的错误集锦,解决填坑

    django默认是有一个admin的后台管理模块,但是丑,功能也不齐全,但是大神给我们已经集成好了xadmin后台,我们拿来用即可,但是呢,django已经升级到2.1版本了,xadmin貌似跟不上节 ...

  6. 适合学习的QT开源项目-SerialTool

    https://github.com/Skiars/SerialTool A cross platform Serial-Port/TCP/UDP debugging tool. SerialTool ...

  7. Leetcode 515. 在每个树行中找最大值

    题目链接 https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/description/ 题目描述 您需要在二叉树的 ...

  8. Java 关键字volatile 与 synchronized 作用与区别

     1,volatile 它所修饰的变量不保留拷贝,直接访问主内存中的.    在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器).为了性能,一个线程会在自己 ...

  9. JDK各版本新特性浅谈

    JDK 5.0 自动拆装箱 枚举 可变参数 泛型 For -each 内省 静态导入 JDK 6.0 console开发控制台程序 轻量级HTTP ServerAPI 支持脚本语言 使用Compile ...

  10. heap&stack的区别

    1. heap (堆)是一个可动态申请的内存空间,一般所有创建的对象和数组都放在这里.stack (栈)是一个先进后出的数据结构,通常用于保存方法(函数)中的参数,局部变量.stack (栈)的空间小 ...