暑假集训Day12 G (定位计数)

题目链接在这里:Problem - G - Codeforces

题目大意是必须要找一对相等的数,然后这两对数的位置是要交叉的。

最朴素的暴力可以是枚举一对数,然后看这对数中间和前后有多少相同的对。

关于区间相同数的个数我们可以通过维护一个前缀和最后用O(1)的复杂度跑出来。

由于我们要求的四个数里面只有两个不同的数,所以优化一下只要枚举这两个数的位置就好了,剩下的可以用前缀和解决

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=3005;
 5 LL t,n,a[MAX],tot;
 6 LL cnt[MAX][MAX],cc[MAX];
 7 struct Node{
 8     LL b[MAX],cn,no;
 9 }stu[MAX];
10 bool cmp(Node x,Node y){
11     return x.cn<y.cn;
12 }
13 LL mul(LL x){return ((x==1||x==0)?1:x*mul(x-1));}
14 LL C(LL x,LL y){
15     return mul(x)/(mul(y)*mul(x-y));
16 }
17 int main(){
18     freopen ("g.in","r",stdin);
19     freopen ("g.out","w",stdout);
20     LL i,j,ans;
21     scanf("%d",&t);
22     while (t--){
23         scanf("%d",&n);
24         memset(cnt,0,sizeof(cnt));
25         tot=0;
26         for (i=1;i<=n;i++){
27             for (j=1;j<=n;j++) cnt[i][j]+=cnt[i-1][j];
28             scanf("%d",a+i),cnt[i][a[i]]++;
29             cc[a[i]]++;
30         }
31         for (i=1;i<=n;i++)
32             if (cc[i]>1){
33                 stu[++tot].cn=cc[i];
34                 stu[tot].no=i;
35             }
36         sort(stu+1,stu+tot+1,cmp);
37         i=1;ans=0;
38         while (stu[i].cn<4 && i<=tot) i++;
39         for (;i<=tot;i++) ans+=C(stu[i].cn,4);
40         ans=0;//cout<<i<<endl;
41         for (i=1;i<n;i++)
42             for (j=i+1;j<=n;j++){
43                 ans+=(cnt[n][a[i]]-cnt[j][a[i]])*cnt[i-1][a[j]];
44                 //cout<<i<<' '<<j<<(cnt[n][a[i]]-cnt[j][a[i]])*cnt[i-1][a[j]]<<endl;
45             }
46         printf("%lld\n",ans);
47     }
48     return 0;
49 }

 

上一篇:牛客java专项练习-day12


下一篇:寒假Day12:最小费用最大流问题