ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

p1908 求逆序对(树状数组)

2020-02-29 10:36:35  阅读:230  来源: 互联网

标签:return 树状 int p1908 离散 数组 ans 逆序


当ai < 105的时候
1.树状数组向上修改,向下查询(即传统方法)。
逆向枚举每一个数,先查询已经插入树状数组中比他小的元素的个数,累加ans;然后再把这个数加入到树状数组。

for(i=n;i>=1;i--)
{
    ans+=getsum(a[i]-1);
	fix(a[i]);
}

代码如下

#include<cstdio>
int a[500007],e[500007],n;
int getsum(int x)
{
	int i,sum=0;
	for(i=x;i;i-=i&-i)
	    sum+=e[i];
    return sum;
}
void fix(int x)
{
	int i;
	for(i=x;i<=n;i+=i&-i)
	   e[i]++;
    return ;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	int ans=0;
	for(int i=n;i>=1;i--)
	{
		ans+=getsum(a[i]-1);
		fix(a[i]);
	}
	printf("%d",ans);
	return 0;
}

2.树状数组向下查询(更新),向上修改。
正向枚举每一个数,先向上查询,查询到的结果就是已经插入到树状数组中的比当前值大的元素的个数。累加ans;
然后向下修改当前值x1,保证当前值的影响范围为向下的。那么如果下次查询x,如果x>x1,向上查找的时候就不会找到x1;如果x<x1,那么向上查找的时候就能够找到x1。

当ai < 109的时候
树状数组的空间开不下,但是我们发现数据n < 105,我们可以用离散的方法,简单理解,就是我们把给出的参差不齐的数,换成大小排列等价的数。例如2、99999999这两个数我们可以换成1、2这样对我们求逆序对是没有影响的。离散之后我们就可以正常用树状数组求逆序对了。

可以不用离散化的函数,用结构体排序或开两个数组记录下标即可这个操作很牛掰
上代码

#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,c[100005],a[100005],b[100005];  //定义数组,b[]为读入的数组,a[]为要离散化后的数组,C[]为树状数组
void add(int x)  //树状数组加入
{
    for(;x<=n;x+=(x&-x))
        c[x]++;  //因为这里只需要1,所以我就写出c[x]++了
}
int getsum(int x)  //树状数组求和,同上面的sum(x)
{
    int sum=0;  //计数的变量
    for(;x;x-=(x&-x))  //累计
        sum+=c[x];
    return sum;  //返回结果
}
bool cmp1(int x,int y)  //离散化需要用的,上面有讲
{
    return b[x]>b[y];
}
int main()
{
    long long ans=0;  //ans为最后的结果
    scanf("%d",&n);  //读入n
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&b[i]);  //读入
        a[i]=i;  //顺便初始化一下a数组
    }
    sort(a+1,a+n+1,cmp1);  //给a数组排序,达到最终的效果
    for(int i=1;i<=n;i++)
    {
        add(a[i]);  //依次加入树状数组
        ans+=getsum(a[i]-1);  //计算结果并累计
    }
    printf("%lld",ans);  //输出ans
    return 0;  //返回
}

就这个码错了
对 做了一上午它还是错的 RE WA TLE
就这样不解释
树状数组太tm难了
太难了
就太难了
太!难!了!
归并排序它不香吗

一小时后冷静更新
我把题解 是两篇的题解复制粘贴到了oj和洛谷测评里
然后它们都没过
而且错的还一样
哈?excuse me?!
oj上归并能过 洛谷归并过不了
oj树状数组0 洛谷树状数组50
记录一下癫狂记录【死亡微笑】

这个是最终对的码

#include<bits/stdc++.h>
#define M 500005
using namespace std;
int a[M],d[M],t[M],n;
int lowbit(int x)
{ return x&-x;
}
void add(int x)//把包含这个数的结点都更新 
{ while(x<=n)//范围 
 { t[x]++;
  x+=lowbit(x);
 }
}
int sum(int x)//查询1~X有几个数加进去了 
{ int res=0;
 while(x>=1)
 { res+=t[x];
  x-=lowbit(x);
 }
 return res;
}
bool cmp(int x,int y)//离散化比较函数 
{ if(a[x]==a[y]) return x>y;//避免元素相同 
 return a[x]>a[y];//按照原序列第几大排列 
}
int main()//402002139
{ //freopen("in.txt","r",stdin);
 long long ans=0;
 cin>>n;
 for(int i=1;i<=n;i++)
 cin>>a[i],d[i]=i;
 sort(d+1,d+n+1,cmp);//离散化 
 for(int i=1;i<=n;i++)
 { add(d[i]);//把这个数放进去 
  ans+=sum(d[i]-1);//累加 
 }
 cout<<ans;
 return 0;
}
Christine_xb 发布了43 篇原创文章 · 获赞 2 · 访问量 806 私信 关注

标签:return,树状,int,p1908,离散,数组,ans,逆序
来源: https://blog.csdn.net/weixin_45885433/article/details/104340457

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有