bzoj4240: 有趣的家庭菜园
又是调成sb的题啊。。。
下午三个多小时就交代给这两题代码还短得要死的题
一眼就是离散化,树状数组&&逆序对
然后又是搞了个WA的做法,枚举分界点
正解要贪心。(不用离散化。。。)
排序后判断当前分在左边和右边
看下那边逆序对少放那边
一个经常用到的结论:我们给原数组标上下表1...n,移动若干次后我们会得到一个新的下标序列,需要的搬运次数就是这个新序列的逆序对数。——CQzhangyu
sun dog
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct node { int x,id; }a[310000]; bool cmp(node n1,node n2){return n1.x>n2.x;} int lslen,ls[310000]; int s[310000]; int lowbit(int x){return x&-x;} void change(int x,int k) { while(x<=300100) { s[x]+=k; x+=lowbit(x); } } int getsum(int x) { int ret=0; while(x>0) { ret+=s[x]; x-=lowbit(x); } return ret; } int ln[310000],rn[310000]; int main() { freopen("data.in","r",stdin); freopen("1.out","w",stdout); int n; scanf("%d",&n);lslen=n; for(int i=1;i<=n;i++) scanf("%d",&a[i].x), a[i].id=i, ls[i]=a[i].x; sort(ls+1,ls+lslen+1); lslen=unique(ls+1,ls+lslen+1)-ls-1; for(int i=1;i<=n;i++) a[i].x=lower_bound(ls+1,ls+lslen+1,a[i].x)-ls; sort(a+1,a+n+1,cmp); //----init------ LL ans=0;int sum,tp; for(int i=1;i<=n;i=tp+1) { sum=i-1; for(int j=i;a[i].x==a[j].x&&j<=n;j++) { int r=getsum(a[j].id-1); ans+=( LL(min(r, sum-r)) ); tp=j; } for(int j=i;j<=tp;j++)change(a[j].id,1); } printf("%lld\n",ans); return 0; }
pain and happy in the cruel world.