• 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('
    ')
    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;
    }
    
  • 相关阅读:
    c#数据类型
    遮罩层
    图片轮播
    js 获取浏览器高度和宽度值
    bootstrap、jquery
    洛谷P1442 铁球落地 题解
    HDU3016 Man Down 题解
    POJ2892 Tunnel Warfare 题解
    HDU2795 Billboard 题解
    CF920F SUM and REPLACE 题解
  • 原文地址:https://www.cnblogs.com/ghostcai/p/13568273.html
Copyright © 2020-2023  润新知