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) 求字符串本质不同子序列个数

Pashmak and Flowers

CF#459 A Pashmak and Garden (水题)

B. Pashmak and Flowers1300 / 思维

CF459E Pashmak and Graph

A. Pashmak and Garden1200 / 思维