CF459D
Pashmak and Parmida's problem
题面翻译
- 给出长度为 \(n(1\le n\le10^6)\) 的序列 \(a(1\le a_i\le10^9)\)。
- \(f(i,j,x)\) 表示 \(a_i\dots a_j\) 中 \(x\) 的出现次数。
- 求有多少对 \(i,j\) 满足 \(f(1,i,a_i) > f(j,n,a_j)\) 且 \(i < j\)。
输入格式
The first line of the input contains an integer $ n $ $ (1<=n<=10^{6}) $ . The second line contains $ n $ space-separated integers $ a_{1},a_{2},...,a_{n} $ $ (1<=a_{i}<=10^{9}) $ .
输出格式
Print a single integer — the answer to the problem.
样例 #1
样例输入 #1
7
1 2 1 1 2 2 1
样例输出 #1
8
样例 #2
样例输入 #2
3
1 1 1
样例输出 #2
1
样例 #3
样例输入 #3
5
1 2 3 4 5
样例输出 #3
0
首先可以预处理f(1,i,a[i]) f(j,n,a[j])
然后考虑类似逆序对的求法
对于每个j 只有i<j 且g[j]的值在[1,f[i]-1]才满足
所以倒序枚举i
每次统计tot+=query(f[i]-1)
再更新add(g[i],1)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[1000005],b[1000005],m;
int tr[1000005*2];
int f[1000005],g[1000005],cnt[1000005],tot;
int lowbit(int x)
{
return x&(-x);
}
void add(int p,int x)
{
for(;p<=n;p+=lowbit(p))
tr[p]+=x;
}
int query(int p)
{
int sum=0;
for(;p;p-=lowbit(p))
sum+=tr[p];
return sum;
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],b[i]=a[i];
sort(b+1,b+n+1);
int m=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+m+1,a[i])-b;
for(int i=1;i<=n;i++)
{
cnt[a[i]]++;
f[i]=cnt[a[i]];
}
memset(cnt,0,sizeof(cnt));
for(int i=n;i>=1;i--)
{
cnt[a[i]]++;
g[i]=cnt[a[i]];
}
for(int i=n;i>=1;i--)
{
tot+=query(f[i]-1);
add(g[i],1);
}
cout<<tot<<"\n";
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号