Educational Codeforces Round 94 (Rated for Div. 2) D. Zigzags

题意:长度为n(n<=3000)的序列a,求\(i<j<k<l\)\(a_i=a_k\)\(a_j=a_l\)的有序对(i,j,k,l)个数

很清晰明了的题面,时间不够没仔细琢磨

先尝试枚举一个位置,再用O(n)的复杂度统计答案,好像不太行..

再尝试枚举两个位置,枚举j和k,此时已经有O(n^2)的复杂度了,如何O(1)统计答案?
注意到j和k确定后,只需要在j左侧找等于a[k]的元素个数,在k右侧找等于a[j]的元素个数,二者相乘即完成了统计

暴力上n个前缀和、后缀和,f[i][j]表示前i位中j出现次数,p[i][j]表示i位以后j出现次数,O(n^2)预处理,O(1)统计就完了

对了,不开LL见祖宗

#include<bits/stdc++.h>

using namespace std;

inline int rd(){
	int ret=0,f=1;char c;
	while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
	while(isdigit(c))ret=ret*10+c-'0',c=getchar();
	return ret*f;
}
#define pc putchar
#define space() pc(' ')
#define nextline() pc('\n')
void pot(int x){if(!x)return;pot(x/10);pc('0'+x%10);}
void out(int x){if(!x)pc('0');if(x<0)pc('-'),x=-x;pot(x);}

const int MAXN = 3005;

int n;
int a[MAXN];

int f[MAXN][MAXN];
int p[MAXN][MAXN];

void solve(){
	memset(f,0,sizeof(f));
	memset(p,0,sizeof(p));
	n=rd();
	for(int i=1;i<=n;i++) a[i]=rd();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++) f[i][j]=f[i-1][j];
		f[i][a[i]]++;	
	}
	for(int i=n;i>=1;i--){
		for(int j=1;j<=n;j++) p[i][j]=p[i+1][j];
		p[i][a[i]]++;
	}	
	long long ans=0;
	for(int j=2;j<=n;j++){
		for(int k=j+1;k<=n;k++){
			ans+=1ll*p[k+1][a[j]]*f[j-1][a[k]];
		}
	}
	cout<<ans<<endl;
}
int main(){
	int T=rd();
	while(T--) solve();
	return 0;
}
posted @ 2020-08-26 22:06  GhostCai  阅读(106)  评论(1编辑  收藏  举报