Educational Codeforces Round 94 (Rated for Div. 2) D. Zigzags
思路:
3000的数据很明显可以暴力,所以我们枚举边界i,k,统计j,l对答案的贡献。
计算j,l的贡献就是,先设a[j]=a[l]=x,然后用数组L[x]统计k左边x的个数,R[x]统计k右边x的个数,所以k在当前位置时,x对答案的贡献就是L[x]*R[x]。但是要注意k是向右移动的,所以用tmp记录k当前位置的总贡献,每次k移动都把tmp加到答案取。k移动时也要注意更新L和R数组,以及tmp,小心当k移动后的位置上的数和移动前位置上的数相同时,不要重复计算了。建议画图想一想。
代码:
#include<iostream> #include<algorithm> #include<fstream> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<deque> #include<cmath> #include<map> #include<queue> #include<bitset> //#include<hash_map> #define sd(x) scanf("%d",&x) #define lsd(x) scanf("%lld",&x) #define ms(x,y) memset(x,y,sizeof x) #define fu(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define all(a) a.begin(),a.end() #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; //using namespace __gnu_cxx; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int maxn=3e3+79; const int mod=1e9+7; const int INF=1e9+7; const double pi=acos(-1); ll a[maxn],L[maxn],R[maxn]; int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); //std::ifstream fil; //fil.open("t.txt"); //freopen("C.in","r",stdin); int T;cin>>T; while(T--) { int n;cin>>n; fu(i,1,n) cin>>a[i]; ll ans=0; //枚举边界 fu(l,1,n) { ll tmp=0; ms(L,0);ms(R,0); fu(r,l+2,n) { R[a[r]]++; } fu(r,l+2,n) { tmp-=L[a[r-1]]*R[a[r-1]]; //当a[r-1]==a[r]时,小心不要重复计算 if(a[r-1]!=a[r]) tmp-=L[a[r]]*R[a[r]]; L[a[r-1]]++; R[a[r]]--; tmp+=L[a[r-1]]*R[a[r-1]]; if(a[r-1]!=a[r]) tmp+=L[a[r]]*R[a[r]]; //加上每个合法的边界对答案的贡献 if(a[l]==a[r]) ans+=tmp; } } cout<<ans<<endl; } return 0; }