【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){//¶Ô³¤¶ÈΪlen(2µÄÃÝ)µÄÊý×é½øÐÐDFT±ä»»
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){//ÕâÒ»²ã½áµã°üº¬µÄÊý×éÔªËØ¸öÊý¶¼ÊÇ(1<<s)
Complex w=Complex(1,0);
for(int j=0;j<(m>>1);++j){//ÕÛ°ëÒýÀí£¬¸ù¾ÝÁ½¸ö×Ó½Úµã¼ÆË㸸½Úµã
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]);
}
}
}
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/

浙公网安备 33010602011771号
