大家好,又见面了,我是全栈君。
1A…火车上写的,,。
学到:
1、明白特征。分类讨论。能够防止计数反复
求逆序数的时候,算出以每一个数为逆序数对的第二个数的情况之和即为序列的逆序数,这样能够防止反复
2、假设没有思路。就先从若干情况入手,自己模拟试试。找规律
这道题的规律就是,如果全部比x[i]小的数个数为c,那么当把第一个数移到序列最后,产生的新的逆序对个数为sum=sum-c+n-1-c;,降低了c,添加了n-1-c
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define lson(i) l,mid,(i)*2 #define rson(i) mid+1,r,((i)*2+1) #define ll rt*2 #define rr (rt*2+1) const int MAXN = 5000+10; struct Node{int l,r,tot;}nodes[MAXN*4]; int x[MAXN],n,d[MAXN],y[MAXN]; void Pushup(int rt) { nodes[rt].tot = nodes[ll].tot + nodes[rr].tot; } void build(int rt, int l, int r) { nodes[rt].l=l; nodes[rt].r=r; nodes[rt].tot=0; if(l == r) { return; } int mid=(l+r)/2; build(ll,l,mid); build(rr,mid+1,r); } void Update(int rt, int p, int v) { if(nodes[rt].l == nodes[rt].r) { nodes[rt].tot=1; return; } int mid=(nodes[rt].l+nodes[rt].r)/2; if(p<=mid) { Update(rt*2,p,v); } else { Update(rr,p,v); } Pushup(rt); } int Query(int rt, int l, int r) { if(l == nodes[rt].l && r == nodes[rt].r) { return nodes[rt].tot; } int mid=(nodes[rt].l+nodes[rt].r)>>1; if(r<=mid)return Query(ll,l,r); else { if(l>mid) { return Query(rr,l,r); } else { return Query(ll,l,mid)+Query(rr,mid+1,r); } } } int main() { freopen("hdu1394.txt","r",stdin); while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) { scanf("%d",&x[i]); x[i]+=1; } build(1,1,n); for(int i=1;i<=n;i++) { Update(1,x[i],1); d[i]=Query(1,1,x[i])-1; } int sum=0,ans=n; for(int i=1;i<=n;i++) { y[i]=Query(1,1,x[i])-1-d[i];//y[i] x[i]右側比之小的数个数 sum+=(i-1-d[i]); } ///////////////////////// /* for(int i=1;i<=n;i++) { printf("i=%d d=%d y=%d\n",i,d[i],y[i]); } printf("sum=%d\n",sum);*/ ////////////// int c; ans=sum; for(int i=1;i<=n;i++) { c=y[i]+d[i]; sum=sum-c+n-1-c; ans=min(ans,sum); } printf("%d\n",ans); } return 0; }
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115719.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...