hdoj 4911 Inversion 树状数组+离散化

题意:给你n个可以重复的无序数列,问经过k次相邻交换后最少还有多少对逆序数

求逆序对可以用树状数组来做,对于重复的元素,可能在sort的时候交换编号

求和的时候要注意去重,还有一种方法就是稳定排序stable_sort

#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define ll __int64
#define N 100000+10
struct ln{
        int id,va;
}in[N];
int a[N],c[N];
int n;
int cmp(ln x,ln y)
{
        return x.va<y.va;
}
int lowbit(int x) { return x&(-x);}
void updata(int t,int value)
{
        for(int i=t;i<=n;i+=lowbit(i))
                c[i]+=value;

}
int getSum(int x)
{
        int temp=0;
        for(int i=x;i>=1;i-=lowbit(i))
                temp+=c[i];
        return temp;
}
int main()
{
        int k;
        while(scanf("%d%d",&n,&k)!=EOF)
        {
                for(int i=1;i<=n;i++)
                {
                        scanf("%d",&in[i].va);
                        in[i].id=i;
                }
                memset(c,0,sizeof(c));
                sort(in+1,in+n+1,cmp);
                a[in[1].id]=1;
                for(int i=2;i<=n;i++)
                {
                        if(in[i].va!=in[i-1].va)
                        a[in[i].id]=i;
                        else
                        a[in[i].id]=a[in[i-1].id];

                }
                ll ans=0;
                for(int i=1;i<=n;i++)
                {
                   updata(a[i],1);
                   printf("%d %d\n",getSum(a[i]),getSum(a[i]-1));
                   int temp=i-getSum(a[i]-1);
                   temp=temp-(getSum(a[i])-getSum(a[i]-1));
                   ans+=temp;
                }
                if(ans-k<0) printf("0\n");
                else
                printf("%I64d\n",ans-k);

        }
        return 0;
}
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define ll __int64
#define N 100000+10
struct ln{
        int id,va;
}in[N];
int a[N],c[N];
int n;
int cmp(ln x,ln y)
{
        return x.va<y.va;
}
int lowbit(int x) { return x&(-x);}
void updata(int t,int value)
{
        for(int i=t;i<=n;i+=lowbit(i))
                c[i]+=value;

}
int getSum(int x)
{
        int temp=0;
        for(int i=x;i>=1;i-=lowbit(i))
                temp+=c[i];
        return temp;
}
int main()
{
        int k;
        while(scanf("%d%d",&n,&k)!=EOF)
        {
                for(int i=1;i<=n;i++)
                {
                        scanf("%d",&in[i].va);
                        in[i].id=i;
                }
                memset(c,0,sizeof(c));
                stable_sort(in+1,in+n+1,cmp);
                for(int i=1;i<=n;i++)
                        a[in[i].id]=i;
                ll ans=0;
                for(int i=1;i<=n;i++)
                {
                   updata(a[i],1);

                   int temp=i-getSum(a[i]);

                   ans+=temp;
                }
                if(ans-k<0) printf("0\n");
                else
                printf("%I64d\n",ans-k);

        }
        return 0;
}
时间: 2024-08-11 05:33:40

hdoj 4911 Inversion 树状数组+离散化的相关文章

HDU 4911 Inversion 树状数组求逆序数对

显然每次交换都能降低1 所以求出逆序数对数,然后-=k就好了.. . _(:зゝ∠)_ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<set> #include<map> #include<iostream> #include<algorithm> using namespace std; #define N 100005 #define

HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences                                  Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)                                             

BZOJ 1227 [SDOI2009] 虔诚的墓主人 离线+树状数组+离散化

鸣谢:140142耐心讲解缕清了我的思路 题意:由于调这道题调的头昏脑涨,所以题意自己搜吧,懒得说. 方法:离线+树状数组+离散化 解析:首先深表本蒟蒻对出题人的敬(bi)意(shi).这道题简直丧心病狂,看完题后大脑一片空白,整个人都不好了,刚开始的思路是什么呢?暴力思想枚举每个墓碑,然后计算每个墓碑的虔诚度,然后再来统计.不过看看数据范围呢?10^9*10^9的矩阵,最多才10^5个树,光枚举就已经超时了,所以肯定不行.(不过要是考试真没思路我就那么搞了- -!) 然后也想到来枚举墓碑,不过

求逆序数模板(树状数组+离散化 || 归并排序法)

一篇不错的讲解:http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html 代码如下:(树状数组+离散化) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=500017; int n; int aa[maxn

Ultra-QuickSort (树状数组离散化)

题目原意是用归并排序,刚学树状数组,就用了下 树状数组的离散化 离散化,是数据范围太大是所借用的利器,举个例子,有四个数99999999 1 123 1583 数据范围太大,而树状数组中的c数组开的范围是数据的范围,这时候就需要离散化,把四个数一次标号为1 2 3 4(即第一个数,第二个数...),按键值排序之后 依次为2 3 4 1(即从小到大排序为第二个数,第三个数...),所以,第二个数是最小的,即f[2]=1,f[3]=2,f[4]=3,f[1]=4,也就是把键值变为了1~n,相对大小还

hdu4325 树状数组+离散化

http://acm.hdu.edu.cn/showproblem.php?pid=4325 Problem Description As is known to all, the blooming time and duration varies between different kinds of flowers. Now there is a garden planted full of flowers. The gardener wants to know how many flower

高桥低桥(树状数组离散化)

1335: 高桥和低桥 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 362  Solved: 62 [Submit][Status][Web Board] Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算"淹了两次".举例说明: 假定高桥和低桥的高度分别是5和2,初始水位为1 第一次

Ultra-QuickSort(树状数组 + 离散化)

Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input seque

HDOJ 5372 Segment Game 树状数组+离散化

因为这题的线段长度是递增的....所以: 题解:对于新插入的线段,查询有多少个线段左端点大于等于该线段的左端点. 再查询有多少个线段的右端点大于该线段右端点, 两者之差就是答案.用两个树状数组搞定.时间复杂度nlog Segment Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 975    Accepted Submiss