hdu 1394(线段树)
来源:互联网 发布:掌趣上游网络牟正文 编辑:程序博客网 时间:2024/05/22 05:04
这道题目是求逆序数的。要得到答案,需要利用一个结论,如果是0到n-1 的排列,那么如果第一个数放到最后,这与这个数列,逆序数减少a[i],增加n-a[i]-1;
隔了几天之后,再做这道题目,发现有点生疏了。
在题目中的数字是从 0--n-1的。因此在初始化的时候要 build( 0,n-1 ,1)
在query 函数里,是查询a[i]到n-1 一段区间里面的逆序数。
time 62ms#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int N=5005;int sum[N<<2];int a[N];void push_up(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1] ; }void build(int l,int r,int rt){ sum[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1);}void updata(int l,int r,int rt,int p){ if(l==r) { sum[rt]++; return ; } int m=(l+r)>>1; if(p<=m) updata(l,m,rt<<1,p); else updata(m+1,r,rt<<1|1,p); push_up(rt);}int query(int l,int r,int rt,int s,int t){ if(s<=l&& t>=r) { return sum[rt]; } int m=(l+r)>>1; int ret=0; if(s<=m) ret+=query(l,m,rt<<1,s,t); if(t>m) ret+=query(m+1,r,rt<<1|1,s,t); return ret;}int main(){ int n; while(~scanf("%d",&n)) { int ans=0; build(0,n-1,1); for(int i=0;i<n;i++) { scanf("%d",&a[i]); ans+=query(0,n-1,1,a[i],n-1); updata( 0,n-1,1,a[i] ); } int ret=ans; for(int i=0;i<n;i++) { ans=(ans-a[i] )+ (n-a[i]-1) ; ret=min(ret,ans ); } printf("%d\n",ret); }}
在使用zkw 线段树的做法的时候,时间减少到了46ms;
贴上代码
#include <iostream>#include <stdio.h>#include <algorithm>#include <memory.h>using namespace std;const int N=5005;int T[N<<2];int M;void push_up(int n){ T[n]=T[n<<1]+T[n<<1|1];}void updata(int n){ for(T[n+=M]+=1,n>>=1;n;n>>=1) push_up(n);}int query(int s,int t){ int ans=0; for(s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1) { if(~s&1) ans+=T[s^1]; if( t&1) ans+=T[t^1]; } return ans;}int a[N];int main(){ int n; while(scanf("%d",&n)!=EOF) { for(M=1;M<=n+1;M<<=1); int sum=0; memset(T,0,sizeof(T)); for(int i=0;i<n;i++) { scanf("%d",&a[i]); a[i]++; <span style="font-family: 'Courier New'; white-space: pre-wrap; color: rgb(0, 128, 0); line-height: 1.5 !important;">//</span><span style="font-family: 'Courier New'; white-space: pre-wrap; color: rgb(0, 128, 0); line-height: 1.5 !important;">注意后面add的时候不能在0位置上add</span> if(a[i]!=n) sum+=query(a[i]+1,n); updata(a[i]); } int ret=sum; for(int i=0;i<n;i++) { sum=sum+(n-a[i])-(a[i]-1); ret=min(ret,sum); } printf("%d\n",ret); }}
0 0
- hdu 1394(线段树)
- hdu 1394(线段树)
- HDU--1394(线段树)
- hdu 1394(线段树)
- HDU 1394(线段树)
- HDU 1394 线段树
- hdu 1394(线段树)
- HDU 1394 线段树
- hdu 1394 线段树
- hdu 1394线段树
- hdu 1394 线段树
- HDU 1394 线段树
- HDU 1394 线段树
- hdu 1394 线段树
- HDU 1394 线段树
- HDU 1394 线段树
- HDU 1394 线段树
- HDU 1394(线段树单点更新)
- POJ 题目1258 Agri-Net(最小生成树)
- poj 2452 RMQ(Sticks Problem)
- web服务器并发访问如何提升
- 同步异步
- 360与百度研发工程师的待遇,工作环境全面对比
- hdu 1394(线段树)
- 【Jason's_ACM_解题报告】Building for UN
- LeetCode[88]Merge Sorted Array
- 关于如何提高Web服务端并发效率的异步编程技术
- Linux程序设计(Linux shell编程二)
- 【总结】 - OC内存管理(2)
- Android列表收缩与展开仿QQ好友列表(非常详细,附源码)
- LeetCode 40.Combination Sum II
- (2817)POJ