首页 > 代码库 > 【FFT】OpenJ_POJ - C17H - Reverse K-th Problem

【FFT】OpenJ_POJ - C17H - Reverse K-th Problem

对每个位置i处理出以其为结尾,且比a(i)大的数有j个的前缀个数,记成一个数组l;同理,处理出以其为开头,且比a(i)大的数有j个的后缀的个数,记成一个数组r。

整个序列中比a(i)大的数的个数的数组就是对l和r数组卷积起来。

于是枚举所有i,FFT,累加答案即可。

但是,有可能有重复的元素,就将a(i)前面的和它相同的数当成比它大,后面的和它相同的数当成比他小即可。

 

存疑:FFT的数组到底要开多大啊?四倍?还是只要是一个比卷积结果数组长度大的2的整数幂次就行了?我倾向于后者。求解。

2#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <cstring>
#include <vector>
using namespace std;
#define EPS 1e-8
const double PI = acos(-1.0);
struct Complex{
    double real,image;
    Complex(double _real,double _image){
        real=_real;
        image=_image;
    }
    Complex(){}
};
Complex operator + (const Complex &c1,const Complex &c2){
    return Complex(c1.real+c2.real,c1.image+c2.image);
}
Complex operator - (const Complex &c1,const Complex &c2){
    return Complex(c1.real-c2.real,c1.image-c2.image);
}
Complex operator * (const Complex &c1,const Complex &c2){
    return Complex(c1.real*c2.real-c1.image*c2.image,c1.real*c2.image+c1.image*c2.real);
}
int rev(int id,int len){
    int ret=0;
    for(int i=0;(1<<i)<len;++i){
        ret<<=1;
        if(id&(1<<i)){
            ret|=1;
        }
    }
    return ret;
}
Complex tmp[2100];
//μ±DFT==1ê±ê?DFT, DFT==-1ê±?òê???DFT
void IterativeFFT(Complex A[],int len, int DFT){//??3¤?è?alen(2μ??Y)μ?êy×é??DDDFT±???
    for(int i=0;i<len;++i){
        tmp[rev(i,len)]=A[i];
    }
    for(int i=0;i<len;++i){
        A[i]=tmp[i];
    }
    for(int s=1;(1<<s)<=len;++s){
        int m=(1<<s);
        Complex wm=Complex(cos(DFT*2*PI/m),sin(DFT*2*PI/m));
        for(int k=0;k<len;k+=m){//?aò?2??áμ?°üo?μ?êy×é?a????êy??ê?(1<<s)
            Complex w=Complex(1,0);
            for(int j=0;j<(m>>1);++j){//??°?òyàí£??ù?Yá???×ó?úμ????????úμ?
                Complex t=w*A[k+j+(m>>1)];
                Complex u=A[k+j];
                A[k+j]=u+t;
                A[k+j+(m>>1)]=u-t;
                w=w*wm;
            }
        }
    }
    if(DFT==-1){
        for(int i=0;i<len;++i){
            A[i].real/=len;
            A[i].image/=len;
        }
    }
}
Complex A[2100],B[2100];

int wq,qw,a[2100],ans[2100][2100],l[2100],r[2100],now,i,j,k,n,m,x;
int read()
{
    char c;
    int ans=0;
    c=getchar();
    while (c<‘0‘ || c>‘9‘) c=getchar();
    while (c>=‘0‘ && c<=‘9‘) ans=ans*10+c-48,c=getchar();
    return ans;
}
int main()
{
    wq=read();
    for (qw=1;qw<=wq;qw++)
    {
        n=read(); m=read();
        for (i=1;i<=n;i++) a[i]=read();
        memset(ans,0,sizeof(ans));
        for (i=1;i<=n;i++)
        {
            memset(l,0,sizeof(l)); l[0]=1;
            memset(r,0,sizeof(r)); r[0]=1;
            now=0;
            for (j=i-1;j>=1;j--)
            {
                if (a[j]>=a[i]) now++;
                l[now]++;
            }
            int len1=now+1;
            now=0;
            for (j=i+1;j<=n;j++)
            {
                if (a[j]>a[i]) now++;
                r[now]++;
            }
            int len2=now+1;
			memset(A,0,sizeof(A));
			memset(B,0,sizeof(B));
            for(int j=0;j<len1;++j){
            	A[j]=Complex(l[j],0);
            }
			for(int j=0;j<len2;++j){
				B[j]=Complex(r[j],0);
			}
			int len;
			for(int j=0;;++j){
            	if((1<<j)>=len1+len2){
                	len=(1<<j);
                	break;
            	}
        	}
            IterativeFFT(A,len,1);
        	IterativeFFT(B,len,1);
			for(int j=0;j<len;++j){
				A[j]=A[j]*B[j];
			}
        	IterativeFFT(A,len,-1);
			for(int j=0;j<len;++j){
            	ans[a[i]][j]+=(int)(A[j].real+0.5);
       	 	}
        }
        for (i=1;i<=m;i++)
        {
            k=read(); x=read();
            printf("%d\n",ans[x][k-1]);
        }
    }
}

【FFT】OpenJ_POJ - C17H - Reverse K-th Problem