【树状数组】CF 459D Pashmak and Parmida's problem
类似树状数组求逆序数
题意:f(1,i,ai)意思为区间1-i内与a[i]相等的个数
同理f(j,n,aj)为区间j-n内与a[j]相同的个数
在1<=i<j<=n的情况下有多少个f(1,i,ai)>f(j,n,aj);
以为a[i]很大所以统计a[i]的个数时用map存
分别统计左边开始a[i]在1-i内的个数
右边开始a[j]在j-n内的个数
然后更新dp[1]的值 每次更新区间[1-dp[1][i] ](增加);
求和的同时再次更新[1-dp[1][i] ](减小);
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <queue> #include <stack> #include <vector> #include <deque> #include <set> #include <map> #define IN freopen ("in.txt" , "r" , stdin); #define OUT freopen ("out.txt" , "w" , stdout); typedef long long LL; const int MAXN = 51111;//点数的最大值 const int MAXM = 20006;//边数的最大值 const int INF = 11521204; const int mod=1000000007; map<int,int >mb; int dp[2][1000100],n; int sum[1000100]; int lowbit(int x) { return x&(-x); } int getsum(int x) { int sum1=0; while(x>0) { sum1+=sum[x]; x-=lowbit(x); } return sum1; } void update(int x,int add) { while(x<=n) { sum[x]+=add; x+=lowbit(x); } } int a[1000010]; int main() { memset(dp,0,sizeof(dp)); memset(sum,0,sizeof(sum)); scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); mb.clear(); for(int i=1; i<=n; i++)//左边开始 { mb[a[i]]++; dp[0][i]=mb[a[i]]; } mb.clear(); for(int i=n; i>=1; i--)//右边开始 { mb[a[i]]++; dp[1][i]=mb[a[i]]; } for (int i=1; i<=n; i++)//先统计 update(dp[1][i],1); long long res=0; for (int i=1; i<=n; i++) { update(dp[1][i],-1);//将这个位置的数减掉 res+=getsum(dp[0][i]-1);//统计res } printf("%I64d\n",res); return 0; }