题目链接

BZOJ3509

题解

化一下式子,就是

\[2A[j] = A[i] + A[k]
\]

所以我们对一个位置两边的数构成的生成函数相乘即可

但是由于这样做是\(O(n^2logn)\)的,我们考虑如何优化

显然可以分块做,我们不对所有数左右求卷积,只对\(B\)个块左右做,这样\(i\)和\(k\)都在块外的情况就可以统计出来

\(i\)或\(k\)在块内的情况可以暴力扫一遍计算

复杂度\(O(Bnlogn + nB)\)

经计算\(B = \sqrt{nlogn}\)最优

但考虑到\(fft\)的常数问题,\(B = 2000\)左右比较合理

复杂度就大概是\(O((nlogn)^{\frac{3}{2}})\)

竟然能\(A\)....

交上去就垫底了。。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define REP(i,n) for (register int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
#define LL long long int
#define res register
using namespace std;
const int maxn = 400005,maxm = 4005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct E{
double a,b;
E(){}
E(double x,double y):a(x),b(y) {}
E(int x,int y):a(x),b(y) {}
inline E operator =(const int& b){
this->a = b; this->b = 0;
return *this;
}
inline E operator =(const double& b){
this->a = b; this->b = 0;
return *this;
}
inline E operator /=(const double& b){
this->a /= b; this->b /= b;
return *this;
}
};
inline E operator *(const E& a,const E& b){
return E(a.a * b.a - a.b * b.b,a.a * b.b + a.b * b.a);
}
inline E operator *=(E& a,const E& b){
return a = E(a.a * b.a - a.b * b.b,a.a * b.b + a.b * b.a);
}
inline E operator +(const E& a,const E& b){
return E(a.a + b.a,a.b + b.b);
}
inline E operator -(const E& a,const E& b){
return E(a.a - b.a,a.b - b.b);
}
const double pi = acos(-1);
int R[maxn];
void fft(E* a,int n,int f){
for (res int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]);
for (res int i = 1; i < n; i <<= 1){
E wn(cos(pi / i),f * sin(pi / i));
for (res int j = 0; j < n; j += (i << 1)){
E w(1,0),x,y;
for (res int k = 0; k < i; k++,w = w * wn){
x = a[j + k],y = w * a[j + k + i];
a[j + k] = x + y; a[j + k + i] = x - y;
}
}
}
if (f == -1) for (int i = 0; i < n; i++) a[i] /= n;
}
E A[maxn],C[maxn];
int N,B,val[maxn],b[maxn],bl[maxm],br[maxm],bi;
LL ans;
void work1(){
for (res int x = 2; x < bi; x++){
int deg1 = 0,deg2 = 0;
for (res int i = 1; b[i] != x; i++)
A[val[i]].a++,deg1 = max(deg1,val[i]);
for (res int i = N; b[i] != x; i--)
C[val[i]].a++,deg2 = max(deg2,val[i]);
int n = 1,L = 0;
while (n <= deg1 + deg2) n <<= 1,L++;
for (res int i = 1; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
fft(A,n,1); fft(C,n,1);
for (res int i = 0; i < n; i++) A[i] *= C[i];
fft(A,n,-1);
for (res int i = bl[x]; i <= br[x]; i++)
ans += (LL)floor(A[val[i] << 1].a + 0.1);
for (res int i = 0; i < n; i++) A[i] = C[i] = 0.0;
}
}
int bac[maxn],M;
void work2(){
for (res int i = 1; i <= N; i++){
for (res int j = i + 1; b[j] == b[i]; j++){
if (val[j] >= val[i] && val[i] >= val[j] - val[i])
ans += bac[val[i] - (val[j] - val[i])];
if (val[j] < val[i] && val[i] + val[i] - val[j] <= 30000)
ans += bac[val[i] + val[i] - val[j]];
}
bac[val[i]]++;
}
REP(i,N) bac[val[i]]--;
for (res int i = N; i; i--){
for (res int j = i - 1; b[j] == b[i]; j--){
if (val[j] >= val[i] && val[i] >= val[j] - val[i])
ans += bac[val[i] - (val[j] - val[i])];
if (val[j] < val[i] && val[i] + val[i] - val[j] <= 30000)
ans += bac[val[i] + val[i] - val[j]];
}
bac[val[i]]++;
}
REP(i,N) bac[val[i]]--;
for (res int x = 1; x <= bi; x++){
for (res int i = bl[x]; i <= br[x]; i++){
for (res int j = i + 1; j <= br[x]; j++){
if (val[j] >= val[i] && val[i] >= val[j] - val[i])
ans -= bac[val[i] - (val[j] - val[i])];
if (val[j] < val[i] && val[i] + val[i] - val[j] <= 30000)
ans -= bac[val[i] + val[i] - val[j]];
}
bac[val[i]]++;
}
for (int i = bl[x]; i <= br[x]; i++) bac[val[i]]--;
}
}
int main(){
N = read(); B = 2000;
REP(i,N){
val[i] = read(),b[i] = i / B + 1,M = max(M,val[i]);
if (b[i] != b[i - 1]) br[b[i - 1]] = i - 1,bl[b[i]] = i;
}
br[b[N]] = N; bi = b[N];
work1();
work2();
printf("%lld\n",ans);
return 0;
}

BZOJ3509 [CodeChef] COUNTARI 【分块 + fft】的更多相关文章

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

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

  2. CC countari & 分块+FFT

    题意: 求一个序列中顺序的长度为3的等差数列. SOL: 对于这种计数问题都是用个数的卷积来进行统计.然而对于这个题有顺序的限制,不好直接统计,于是竟然可以分块?惊为天人... 考虑分块以后的序列: ...

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

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

  4. BZOJ3509: [CodeChef] COUNTARI

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

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

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

  6. BZOJ 3509: [CodeChef] COUNTARI

    3509: [CodeChef] COUNTARI Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 883  Solved: 250[Submit][S ...

  7. BZOJ 3509 分块FFT

    思路: 跟今年WC的题几乎一样 (但是这道题有重 不能用bitset水过去) 正解:分块FFT http://blog.csdn.net/geotcbrl/article/details/506364 ...

  8. CodeChef COUNTARI Arithmetic Progressions(分块 + FFT)

    题目 Source http://vjudge.net/problem/142058 Description Given N integers A1, A2, …. AN, Dexter wants ...

  9. CodeChef - COUNTARI Arithmetic Progressions (FFT)

    题意:求一个序列中,有多少三元组$(i,j,k)i<j<k $ 满足\(A_i + A_k = 2*A_i\) 构成等差数列. https://www.cnblogs.com/xiuwen ...

随机推荐

  1. 身份证扫描识别/身份证OCR识别的正确姿势,你get到了吗?

    自从国家规定电信实名制之后,实名制已经推广到各个领域:办理通信业务需要实名制.银行开户需要实名制.移动支付需要实名制,就连注册个自媒体账户都需要实名制. 而实名制的背后,就是身份证信息的采集和录入验证 ...

  2. 180726-InfluxDB基本概念小结

    InfluxDB基本概念小结 InfluxDB作为时序数据库,与传统的关系型数据库相比而言,还是有一些区别的,下面尽量以简单明了的方式介绍下相关的术语概念 I. 基本概念 mysql influxdb ...

  3. redis主从配置+sentinel哨兵

    redis主从配置+sentinel哨兵 1:编译环境准备 1.1环境确认 Redis是一个开源.支持网络.基于内存.键值对存储数据库,使用ANSI C编写.所以在搭建Redis服务器时需要C语言的编 ...

  4. 3星|《科技投资新时代》:TMT行业资讯汇编

    科技投资新时代:TMT投资方法.趋势与热点聚焦 全书共6章,前4章是一些投资与分析的基本方法与技巧,第5章集中讲通信行业的现状与趋势,第6章讲大数据.物联网.全面屏等TMT行业热点. 总体来说数据.信 ...

  5. python基础-02-while格式化逻辑运算

    python其他知识目录 1.循环打印“我是小马过河” while True:    print('我是小马过河') #4.用while从一打印到10 #5.请通过循环,1 2 3 4 5 6 8 9 ...

  6. $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 区别

    PHP $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 的区别 PHP $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 通常情况下,PHP ...

  7. “Hello World!”团队第六周的第一次会议

    今天是我们团队“Hello World!”团队第六周召开的第一次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.Todo List 六.会议照片 七.燃尽图 一.会议时间 ...

  8. Junit4 单元测试框架的常用方法介绍

    Junit 介绍: Junit是一套框架(用于JAVA语言),由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework),即 ...

  9. psp项目计划

    日期/任务 听课 编写程序 阅读书籍 查阅资料 日总计 周一 2h 0.5h     2.5 周二     1h   1 周三     1h     周四 2h 0.5h     2.5 周五   3 ...

  10. 【软工实践】第四次作业--爬虫结合WordCount

    结对同学博客链接 本次作业博客链接 github项目地址 具体分工 我主要负责用python写爬虫部分,他负责C++部分 PSP表格 解题思路 代码的核心思路是利用爬虫,爬取论文网址,之后吧对应信息( ...