codeforces 459D - Pashmak and Parmida's problem【离散化+处理+逆序对】

题目:codeforces 459D - Pashmak and Parmida‘s problem

题意:给出n个数ai,然后定义f(l,?r,?x) 为ak
= x,且l<=k<=r,的k的个数,求 i,?j (1?≤?i?<?j?≤?n) ,f(1,?i,?ai)?>?f(j,?n,?aj).,有多少对满足条件的i,j。

分类:逆序数,线段树,离散化,

分析:这是一道不错的数据结构题目,比较灵活。推一下第一组样例之后发现时让求一个逆序数的题目,但是不是单纯的求逆序数。

第一组样例:

1 2 1 1 2 2 1

然后我们按数的出现的次数从前往后编号,得到:

1 1 2 3 2 3 4

在从后往前编号:得到

4 3 3 2 2 1 1

然后我们从第二组数中的数在第一组数中找逆序对就是ans。

当前给出的数是1e-9次方,所以要先离散化一次,然后可以用线段树求逆序数的方法就ok。要注意的是ans会超int

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 1001000;
int a[N],b[N],c[N],sum[N];
struct Node
{
    int l,r,num;
};
Node tree[4*N];
map<int,int> m1,m2;
void build(int l,int r,int o)
{
    tree[o].l=l,tree[o].r=r;
    tree[o].num=0;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    build(l,mid,o<<1);
    build(mid+1,r,o+o+1);
}
void update(int t,int o)
{
    if(tree[o].l==tree[o].r && tree[o].l==t)
    {
        tree[o].num++;
        return ;
    }
    int mid=(tree[o].l+tree[o].r)>>1;
    if(t>mid)
        update(t,o+o+1);
    else
        update(t,o+o);
    tree[o].num=tree[o+o].num+tree[o+o+1].num;
}
int query(int l,int r,int o)
{
    //printf("%d %d %d %d\n",l,r,tree[o].l,tree[o].r);
    if(tree[o].l==l && tree[o].r==r)
    {
        return tree[o].num;
    }
    int mid=(tree[o].l+tree[o].r)>>1;
    if(r<=mid)
        return query(l,r,o+o);
    else if(l>mid)
        return query(l,r,o+o+1);
    else
        return query(l,mid,o*2)+query(mid+1,r,o*2+1);
}
int main()
{
    //freopen("Input.txt","r",stdin);
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        int cnt=1;
        for(int i=0;i<n;i++)  //离散化
        {
            if(!m1[a[i]])
                m1[a[i]]=cnt++;
            a[i]=m1[a[i]];
        }
        cnt = 0;
        memset(sum,0,sizeof(sum));
        for(int i=0;i<n;i++)
        {
            sum[a[i]]++;
            b[i]=sum[a[i]];
            cnt=max(cnt,b[i]);
        }
        memset(sum,0,sizeof(sum));
        for(int i=n-1;i>=0;i--)
        {
            sum[a[i]]++;
            c[i]=sum[a[i]];
        }
        build(1,cnt,1);
        long long ans=0;
        for(int i=0;i<n;i++)
        {
            if(c[i]<cnt)
                ans+=query(c[i]+1,cnt,1);
            update(b[i],1);
        }
        printf("%lld\n",ans);
        m1.clear();
        m2.clear();
    }
    return 0;
}

codeforces 459D - Pashmak and Parmida's problem【离散化+处理+逆序对】

时间: 2024-11-24 18:10:49

codeforces 459D - Pashmak and Parmida's problem【离散化+处理+逆序对】的相关文章

CodeForces 459D Pashmak and Parmida&#39;s problem

Pashmak and Parmida's problem Time Limit:3000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 459D Description Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she

Codeforces Round #261 (Div. 2)459D. Pashmak and Parmida&#39;s problem(求逆序数对)

题目链接:http://codeforces.com/contest/459/problem/D D. Pashmak and Parmida's problem time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Parmida is a clever girl and she wants to participate in O

Codeforces 459D Pashmak and Parmida&#39;s problem(树状数组)

题目链接:Codeforces 459D Pashmak and Parmida's problem 题目大意:给定一个序列,定义f(l,r,x)为l≤k≤r并且ak=x的k的个数,求1≤i<j≤n的情况下,f(1,i,ai)<f(j,n,aj)的个数. 解题思路:预处理出f(1,i,ai),f(j,n,aj)值,然后用树状数组维护个数. #include <cstdio> #include <cstring> #include <algorithm> us

Codeforcecs 459D Pashmak and Parmida&#39;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; typed

Codeforces Round #261 (Div. 2) D. Pashmak and Parmida&#39;s problem (树状数组求逆序数 变形)

题目链接 题意: 给出一些数a[n],求(i, j), i<j 的数量,使得:f(1, i, a[i]) > f(j, n, a[j]) . f(lhs, rhs, x) 指在 { [lhs, rhs]范围中,a[k]的值=x } 的数量. 1.  f(1, i, a[i]) 就是指a[i]前面包括a[i]的数中,有几个值=a[i]. 2.  f(j, n, a[j]) 就是指a[j]后面包括a[j]的数中有几个值=a[j]. 虽然a[x]范围不小,但是n的范围是1000,不是很大,所以我们可

【CF 459D】 Pashmak and Parmida&#39;s problem

[CF 459D] Pashmak and Parmida's problem 预处理+线段树求逆序对 新学了树状数组 很适合这题 来一发 代码如下: #include <iostream> #include <cstdio> #include <cstdlib> #include <map> #include <cstring> #define ll long long using namespace std; map <int,int&

Codeforces Round #261 (Div. 2) D. Pashmak and Parmida&#39;s problem (树状数组)

D. Pashmak and Parmida's problem time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partn

Codeforces Round 261 Div.2 D Pashmak and Parmida&#39;s problem --树状数组

题意:给出数组A,定义f(l,r,x)为A[]的下标l到r之间,等于x的元素数.i和j符合f(1,i,a[i])>f(j,n,a[j]),求有多少对这样的(i,j). 解法:分别从左到右,由右到左预处理到某个下标为止有多少个数等于该下标,用map维护. 然后树状数组更新每个f(j,n,a[j]),预处理完毕,接下来,从左往右扫过去,每次从树状数组中删去a[i],因为i != j,i不能用作后面的统计,然后统计getsum(inc[a[i]]-1), (inc表示从左到右),即查询比此时的a[i]

CF459D Pashmak and Parmida&#39;s problem (树状数组)

Codeforces Round #261 (Div. 2)   题意:给出数组A,定义f(l,r,x)为A[]的下标l到r之间,等于x的元素数.i和j符合f(1,i,a[i])>f(j,n,a[j]),求i和j的种类数. 题解:使用树状数组统计小于某数的元素数量. 我们可以先把f(1,i,a[i])和f(j,n,a[j])写出来,观察一下,例如样例1: n=7 A 1 2 1 1 2 2 1 R 4 3 3 2 2 1 1 L 1 1 2 3 2 3 4 其中A为给定的数组,Rj为f(j,n,