codeforces459D:Pashmak and Parmida's problem
Description
Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partner to be clever too (although he's not)! Parmida has prepared the following test problem for Pashmak.
There is a sequence a that consists of n integers a1, a2, ..., an. Let's denote f(l, r, x) the number of indices k such that: l ≤ k ≤ r and ak = x. His task is to calculate the number of pairs of indicies i, j (1 ≤ i < j ≤ n) such that f(1, i, ai) > f(j, n, aj).
Help Pashmak with the test.
Input
The first line of the input contains an integer n (1 ≤ n ≤ 106). The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 109).
Output
Print a single integer — the answer to the problem.
Examples
Input
7
1 2 1 1 2 2 1
Output
8
Input
3
1 1 1
Output
1
Input
5
1 2 3 4 5
Output
0
正解:离散化+树状数组
解题报告:
首先离散化之后,可以预处理一下每个元素的前驱相等元素个数和后继相等元素个数,O(NlogN)
之后我们可以得到每个元素的两个值,前驱个数值pre[i]和后继个数值next[i],我们的任务就是查找i和j满足pre[i]>next[j] && i<j的个数。
感觉是不是很像逆序对?直接从后往前往树状数组中插入next值(记得上界是n,处理一下0),每次查找比当前pre小的next个数,因为我们是从后往前插入的next,所以可以保证i<j
codeforces的评测机真快,100w数据0.4S,丝毫不虚
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long LL; 15 const int MAXN = 1000011; 16 int n,a[MAXN],u[MAXN]; 17 int pre[MAXN],next[MAXN]; 18 int jump1[MAXN],jump2[MAXN]; 19 bool vis[MAXN]; 20 int shu[MAXN],L;//树状数组维护共有多少个小于他的数 21 LL ans; 22 struct node{ 23 int val,id; 24 }b[MAXN]; 25 26 inline int getint() 27 { 28 int w=0,q=0; 29 char c=getchar(); 30 while((c<'0' || c>'9') && c!='-') c=getchar(); 31 if (c=='-') q=1, c=getchar(); 32 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); 33 return q ? -w : w; 34 } 35 36 inline bool cmp(node q,node qq){ if(q.val==qq.val) return q.id<qq.id; return q.val<qq.val; } 37 38 inline void add(int x,int val){ 39 while(x<=n+1) { 40 shu[x]+=val; 41 x+=x&(-x); 42 } 43 } 44 45 inline int query(int x){ 46 int total=0; 47 while(x) { 48 total+=shu[x]; 49 x-=x&(-x); 50 } 51 return total; 52 } 53 54 inline void work(){ 55 n=getint(); for(int i=1;i<=n;i++) u[i]=b[i].val=a[i]=getint(),b[i].id=i,jump2[i]=n+1; 56 sort(b+1,b+n+1,cmp); 57 for(int i=1;i<=n;i++) if(b[i].val==b[i-1].val) jump1[b[i].id]=b[i-1].id,jump2[b[i-1].id]=b[i].id; 58 sort(u+1,u+n+1); 59 L=unique(u+1,u+n+1)-u-1; 60 for(int i=1;i<=n;i++) a[i]=lower_bound(u+1,u+L+1,a[i])-u; 61 int x; 62 for(int i=1;i<=n;i++) { 63 if(vis[i]) continue; vis[i]=1; 64 x=i; while(x<=n) x=jump2[x],pre[x]=pre[jump1[x]]+1,vis[x]=1; 65 66 } 67 memset(vis,0,sizeof(vis)); 68 for(int i=n;i>=1;i--) { 69 if(vis[i]) continue; vis[i]=1; 70 x=i; while(x) x=jump1[x],next[x]=next[jump2[x]]+1,vis[x]=1; 71 } 72 73 for(int i=n;i;i--) { 74 ans+=query(pre[i]); 75 add(next[i]+1,1); 76 } 77 printf("%lld",ans); 78 } 79 80 int main() 81 { 82 work(); 83 return 0; 84 }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!