Codeforcecs 459D Pashmak and Parmida's problem 树状数组 OR 分治
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforcecs 459D Pashmak and Parmida's problem 树状数组 OR 分治相关的知识,希望对你有一定的参考价值。
http://codeforces.com/contest/459/problem/D
题意:定义:f(l,r,x) [l,r]内x的个数 ,n个数,a[i] n<=1e5,a[i]<=1e9
问i<j时满足f(1,i,a[i]) > f(j,n,a[j]) 的(i,j)对数?
预处理出后缀f(j) 插入到BIT中 枚举i,查询mp[a[i]]-1,后更新BIT即可.
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> ii; const ll mod=1e9+7; const ll inf=1e18; const int N=5e6+20; const int M=2e6; //f(1,i,a[i]) > f(j,n,a[j]) ll c[N],n,a[N]; map<ll,ll> mp,mk; int lowbit(int x) { return x&(-x); } void add(int p,int x) { for(int i=p;i<=M;i+=lowbit(i)) c[i]+=x; } ll sum(int p) { ll res=0; for(int i=p;i>=1;i-=lowbit(i)) res+=c[i]; return res; } int main() { //ios::sync_with_stdio(false); while(cin>>n) { mp.clear(),mk.clear(); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=n;i>=1;i--) { mp[a[i]]++; add(mp[a[i]],1); } ll ans=0; for(int i=1;i<n;i++) { mk[a[i]]++; add(mp[a[i]],-1); mp[a[i]]--; ans+=sum(mk[a[i]]-1); } cout<<ans<<endl; } return 0; }
标程的分治解法
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int INF = 1000000000; const int MAX = 1000005; int a[MAX], tmp[MAX], cnt[MAX], le[MAX], ri[MAX]; long long solve(int l, int r) { if (r - l < 2) return 0; int mid = (l + r) / 2; long long ret = solve(l, mid) + solve(mid, r); int p1 = l, p2 = mid; while (p1 != mid || p2 != r) { int val1 = (p1 < mid ? le[p1] : INF); int val2 = (p2 < r ? ri[p2] : INF); if (val1 <= val2) { p1++; ret += p2 - mid; } else p2++; } merge(le + l, le + mid, le + mid, le + r, tmp); for (int i = 0; i < r - l; i++) le[i + l] = tmp[i]; merge(ri + l, ri + mid, ri + mid, ri + r, tmp); for (int i = 0; i < r - l; i++) ri[i + l] = tmp[i]; return ret; } int main() { ios::sync_with_stdio(false); int n; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; tmp[i] = a[i]; } sort(tmp, tmp + n); for (int i = 0; i < n; i++) a[i] = lower_bound(tmp, tmp + n, a[i]) - tmp; for (int i = 0; i < n; i++) { cnt[a[i]]++; le[i] = cnt[a[i]]; } memset(cnt, 0, sizeof(cnt)); for (int i = n - 1; i >= 0; i--) { cnt[a[i]]++; ri[i] = cnt[a[i]]; } cout << solve(0, n) << endl; return 0; }
以上是关于Codeforcecs 459D Pashmak and Parmida's problem 树状数组 OR 分治的主要内容,如果未能解决你的问题,请参考以下文章
Codeforcecs1183H Subsequence(hard version) 求字符串本质不同子序列个数
CF#459 A Pashmak and Garden (水题)