题意:

  求一个序列中顺序的长度为3的等差数列.

SOL:

  对于这种计数问题都是用个数的卷积来进行统计.然而对于这个题有顺序的限制,不好直接统计,于是竟然可以分块?惊为天人...

  考虑分块以后的序列:

    一个块内直接枚举统计三个或两个在块内的.

    只有一个在当前块我们假设它是中间那个,对左右其它块做卷积.

  但是还是感觉复杂度有点玄学啊...

  我比较傻逼...一开始块内统计根本没有想清楚...最后做卷积硬生生把复杂度变成了 $\sqrt{N}*N*log(N)$...

  改了一个晚上终于没忍住看标程...我是傻逼明明a的范围比n小...

CODE:(tle的代码不想改了= =)

  

/*=================================
# Created time: 2016-04-19 16:09
# Filename: cccountari.cpp
# Description: Ploblem from codechef countari
=================================*/
#define me AcrossTheSky&HalfSummer11
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> #include <set>
#include <stack>
#include <queue>
#include <vector> #define lowbit(x) (x)&(-x)
#define Abs(x) ((x) > 0 ? (x) : (-(x)))
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define getlc(a) ch[(a)][0]
#define getrc(a) ch[(a)][1] #define maxn 500005
#define maxm 100005
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull; template<class T> inline
void read(T& num){
num = 0; bool f = true;char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();}
while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();}
num = f ? num: -num;
}
int outs[100];
template<class T> inline
void write(T x){
if (x==0) {putchar('0'); putchar(' '); return;}
if (x<0) {putchar('-'); x=-x;}
int num=0;
while (x){ outs[num++]=(x%10); x=x/10;}
FORM(i,num-1,0) putchar(outs[i]+'0'); putchar(' ');
}
/*==================split line==================*/
const double pi=acos(-1);
struct cpx{
double x,y;
inline double real(){return x;}
cpx(double a=0,double b=0):x(a),y(b){}
}f[maxn],g[maxn],eps[maxn],inv_eps[maxn]; inline cpx operator +(cpx a,cpx b){return cpx(a.x+b.x,a.y+b.y);}
inline cpx operator -(cpx a,cpx b){return cpx(a.x-b.x,a.y-b.y);}
inline cpx operator /(cpx a,double b){return cpx(a.x/b,a.y);}
inline cpx operator *(cpx a,cpx b){return cpx(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
inline cpx conj(cpx a){return cpx(a.x,-a.y);} inline void get_eps(int p){
double angle=2.0*pi/p;
FORP(i,0,p-1) eps[i]=cpx(cos(angle*i),sin(angle*i));
FORP(i,0,p-1) inv_eps[i]=conj(eps[i]);
}
inline void fft(int n,cpx* buffer,cpx* eps){
for (int i = 0, j = 0;i < n; i++){
if (i > j) swap(buffer[i],buffer[j]);
for (int l = n >> 1;(j ^= l) < l;l >>= 1);
}
for (int i = 2; i <= n; i <<= 1){
int m = i >> 1;
for (int j = 0; j < n; j += i)
for (int k = 0; k != m; k++){
cpx z = buffer[j + m + k] * eps[n / i * k];
buffer[j + m + k] = buffer[j + k] - z;
buffer[j + k] = buffer[j + k] + z;
}
}
}
ll n,k,block,num;
ll prec[30004],c[30040],suf[40000];
//bool vis[40000];
ll ans=0;
ll maxa=0;
struct Range{ ll l,r; } rg[1000];
struct Infor{ ll val,pos;} a[100005]; int main(){
read(n);
block=3;
if ((int)n/sqrt(n)>3) block=(int)n/sqrt(n);
FORP(i,1,n) {
read(a[i].val);
g[a[i].val].x++;
maxa=max(maxa,a[i].val);
a[i].pos=(i-1)/block+1;
suf[a[i].val]++;
} ll k=1; maxa*=2;
while (k<maxa) k<<=1;
k<<=1;
get_eps(k); num=a[n].pos;
FORP(i,1,num) rg[i].l=(i-1)*block+1,rg[i].r=min(n,(i)*block);
FORP(i,1,num){
FORP(j,rg[i].l,rg[i].r) c[a[j].val]++;
FORP(l,rg[i].l,rg[i].r-1){
suf[a[l].val]--;
FORP(r,l+1,rg[i].r) {
suf[a[r].val]--;
if (a[l].val==a[r].val) ans+=suf[a[l].val]+prec[a[l].val];
else
{
int x=a[l].val-(a[r].val-a[l].val);
if (x>0) ans+=prec[x];
x=a[r].val+(a[r].val-a[l].val);
if (x>0) ans+=suf[x];
}
}
FORP(r,l+1,rg[i].r) suf[a[r].val]++;
}
FORP(j,rg[i].l,rg[i].r) prec[a[j].val]+=c[a[j].val],c[a[j].val]=0;
suf[a[rg[i].r].val]--;
}
FORP(i,rg[1].l,rg[1].r) g[a[i].val].x--;
FORP(i,2,num-1){
//memset(f,0,sizeof(f)); memset(g,0,sizeof(g));
FORP(j,rg[i-1].l,rg[i-1].r) f[a[j].val].x++;
FORP(j,rg[i-1].l,rg[i-1].r) g[a[j].val].x--;
fft(k,f,eps); fft(k,g,eps);
FORP(j,0,k-1) f[j]=f[j]*g[j];
fft(k,f,inv_eps);
FORP(j,rg[i].l,rg[i].r) ans+=(ll)(f[a[j].val+a[j].val].x/k+0.5);
}
write(ans); puts("");
}

调下块大小a掉了

/*=================================
# Created time: 2016-04-19 16:09
# Filename: cccountari.cpp
# Description: Ploblem from codechef countari
=================================*/
#define me AcrossTheSky&HalfSummer11
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> #include <set>
#include <stack>
#include <queue>
#include <vector> #define lowbit(x) (x)&(-x)
#define Abs(x) ((x) > 0 ? (x) : (-(x)))
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define getlc(a) ch[(a)][0]
#define getrc(a) ch[(a)][1] #define maxn 100005
#define maxm 100005
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull; template<class T> inline
void read(T& num){
num = 0; bool f = true;char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();}
while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();}
num = f ? num: -num;
}
int outs[100];
template<class T> inline
void write(T x){
if (x==0) {putchar('0'); putchar(' '); return;}
if (x<0) {putchar('-'); x=-x;}
int num=0;
while (x){ outs[num++]=(x%10); x=x/10;}
FORM(i,num-1,0) putchar(outs[i]+'0'); //putchar(' ');
}
/*==================split line==================*/
const double pi=acos(-1);
struct cpx{
double x,y;
cpx(double a=0,double b=0):x(a),y(b){}
}f[maxn],g[maxn],eps[maxn],inv_eps[maxn]; inline cpx operator +(cpx a,cpx b){return cpx(a.x+b.x,a.y+b.y);}
inline cpx operator -(cpx a,cpx b){return cpx(a.x-b.x,a.y-b.y);}
inline cpx operator *(cpx a,cpx b){return cpx(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
inline cpx conj(cpx a){return cpx(a.x,-a.y);} inline void get_eps(int p){
double angle=2.0*pi/p;
FORP(i,0,p-1) eps[i]=cpx(cos(angle*i),sin(angle*i));
FORP(i,0,p-1) inv_eps[i]=conj(eps[i]);
}
inline void fft(int n,cpx* buffer,cpx* eps){
for (int i = 0, j = 0;i < n; i++){
if (i > j) swap(buffer[i],buffer[j]);
for (int l = n >> 1;(j ^= l) < l;l >>= 1);
}
for (int i = 2; i <= n; i <<= 1){
int m = i >> 1;
for (int j = 0; j < n; j += i)
for (int k = 0; k != m; k++){
cpx z = buffer[j + m + k] * eps[n / i * k];
buffer[j + m + k] = buffer[j + k] - z;
buffer[j + k] = buffer[j + k] + z;
}
}
}
int n,k,block,num;
int prec[30010],c[30010],suf[30100];
ll ans=0;
int maxa=0;
struct Range{ int l,r; } rg[10000];
struct Infor{ int val,pos;} a[maxn]; int main(){
read(n);
block=4000;
//if ((ll)n/sqrt(n)>3) block=(ll)n/sqrt(n);
block=min(block,n);
FORP(i,1,n) {
read(a[i].val);
maxa=max(maxa,a[i].val);
a[i].pos=(i-1)/block+1;
suf[a[i].val]++;
} int k=1; //maxa*=2;
while (k<maxa) k<<=1;
k<<=1;
get_eps(k); num=a[n].pos;
FORP(i,1,num) rg[i].l=(i-1)*block+1,rg[i].r=(i)*block; rg[num].r=n;
FORP(i,1,num){
FORP(j,rg[i].l,rg[i].r) c[a[j].val]++;
FORP(l,rg[i].l,rg[i].r-1){
suf[a[l].val]--;
FORP(r,l+1,rg[i].r) {
suf[a[r].val]--;
if (a[l].val==a[r].val) ans+=suf[a[l].val]+prec[a[l].val];
else
{
int x=a[l].val-(a[r].val-a[l].val);
if (x>0 && x<=maxa) ans+=prec[x];
x=a[r].val+(a[r].val-a[l].val);
if (x>0 && x<=maxa) ans+=suf[x];
}
}
FORP(r,l+1,rg[i].r) suf[a[r].val]++;
}
suf[a[rg[i].r].val]--;
FORP(j,0,maxa) f[j]=cpx(prec[j],0),g[j]=cpx(suf[j],0);
FORP(j,maxa+1,k) f[j]=cpx(0.0,0),g[j]=cpx(0.0,0);
fft(k,f,eps); fft(k,g,eps);
FORP(j,0,k-1) f[j]=f[j]*g[j];
fft(k,f,inv_eps);
FORP(j,rg[i].l,rg[i].r) ans+=trunc(f[a[j].val+a[j].val].x/k+0.5); FORP(j,rg[i].l,rg[i].r) prec[a[j].val]+=c[a[j].val],c[a[j].val]=0; }
/*FORP(i,2,num-1){
memset(f,0,sizeof(f)); memset(g,0,sizeof(g));
FORP(j,1,rg[i].l-1) f[a[j].val].x++;
FORP(j,rg[i].r+1,n) g[a[j].val].x++;
fft(k,f,eps); fft(k,g,eps);
FORP(j,0,k-1) f[j]=f[j]*g[j];
fft(k,f,inv_eps);
//FORP(j,0,maxa) printf("%d ",(int)(f[j].x/k+0.5)); puts("");
FORP(j,rg[i].l,rg[i].r) ans+=(int)(f[a[j].val+a[j].val].x/k+0.5);
}*/
write(ans); puts("");
//printf("%lf",clock()-t);
}

CC countari & 分块+FFT的更多相关文章

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

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

  2. BZOJ 3509 分块FFT

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

  3. CC Arithmetic Progressions (FFT + 分块处理)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题目:给出n个数,选出三个数,按下标顺序形成等差数 ...

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

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

  5. BZOJ3509 [CodeChef] COUNTARI 【分块 + fft】

    题目链接 BZOJ3509 题解 化一下式子,就是 \[2A[j] = A[i] + A[k]\] 所以我们对一个位置两边的数构成的生成函数相乘即可 但是由于这样做是\(O(n^2logn)\)的,我 ...

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

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

  7. 【做题】codechefCOUNTARI——分块FFT

    记本题数组长度为\(n\),权值大小为\(m\). 首先,暴力显然是\(O(n^2)\)的. 先瞄一眼tag,然后发现这是FFT. 显然,问题的关键在于要满足i,j,k之间的位置关系.于是考虑分治FF ...

  8. cf 472G Design Tutorial: Increase the Constraints 分块+压位/FFT

    题目大意 给出两个\(01\)序列\(A\)和\(B\) 哈明距离定义为两个长度相同的序列中,有多少个对应位置上的数字不一样 "00111" 和 "10101" ...

  9. luogu1919 A*BProblem升级版 (FFT)

    把一个n位数看做n-1次的多项式,每一项的系数是反过来的每一位最后每一项系数进进位搞一搞就行了(数组一定要开到2的次数..要不然极端数据会RE) #include<cstdio> #inc ...

随机推荐

  1. ES6学习笔记一

    块级作用域:在ES5中只有全局作用域与函数作用域,ES6中新增的块级作用域避免变量的覆盖与泄露.考虑到代码运行环境,在块级作用域中应避免声明函数,最好用函数表达式的方式声明. let与const:le ...

  2. JS 深浅拷贝

    首先理解概念 浅拷贝: 只复制对象的基本类型, 对象类型, 仍属于原来的引用. 深拷贝: 不紧复制对象的基本类, 同时也复制原对象中的对象.就是说完全是新对象产生的. 首先看浅拷贝 //浅拷贝 var ...

  3. Cordova环境搭建 & HelloWorld

    目前的手机APP有三类:原生APP,WebAPP,HybridApp:HybridApp结合了前两类APP各自的优点,越来越流行. Cordova就是一个中间件,让我们把WebAPP打包成Hybrid ...

  4. 算法练习_图的连通性问题(JAVA)

    一.问题 1.问题描述: 有n个点(1...n),输入整数对(8,9),表示8,9点之间存在相互的连接关系. 动态连通性问题--编写一段程序过滤掉所以无意义的整数对,即为在不破坏图连通性的前提下,以最 ...

  5. Qt 程序打包发布

    Qt 官方开发环境使用的动态链接库方式,在发布生成的exe程序时,需要复制一大堆 dll,Qt 官方开发环境里自带了一个工具:windeployqt.exe.在Qt安装目录如:C:\Qt\Qt5.7. ...

  6. 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。系统发布第二天访问链接关闭问题。

    解决Mysql连接池被关闭  ,hibernate尝试连接不能连接的问题. (默认MySQL连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池. 所以系统发布第二天访问会 ...

  7. 用DllImport引用的外部DLL文件如何通过clickonce发布

    在.net中非托管代码或非COM组件的外部DLL文件只能用DllImport的方式使用,但是在clickonce方式发布时不会自动包含到发布清单中去,办法是在项目中先把外部DLL文件作为普通文件添加进 ...

  8. 编译安装 varnish-4.1.2和yum 安装 varnish-4.0.3

    vanish可以让用户自己选择缓存数据是存于内存还是硬盘,存于内存一般基于二八法则即常访问的数据是磁盘存储的总数据五分之一,因此内存也应该是硬盘文件大概五分之一.如果有多台vanish则,总内存满足即 ...

  9. 把包发布到npm官网

    一.包 包就是多模块的集合,CommonJS的包规范给程序员提供了组织模块的标准,减少沟通成本. 规范: 所有的模块放在demo文件夹下(包名)的lib文件夹里面 在lib文件夹的同级目录下新建ind ...

  10. 创建cocos项目并打包