AT3625 Increment and Swap 题解

Doveqise

2019-05-04 10:02:47

Solution

2017年AtCoder某场比赛的题 前几天上课刚讲过 ~~为啥没人做~~ 用线段树维护一下min和add ~~水一水就过去了(大雾)~~ 细节下见代码↓ ```cpp #include<bits/stdc++.h> using namespace std; #define N 200005 #define inf 0x7fffffff #define ll long long int n,mn[N<<2],add[N<<2],b[N],a[N]; ll ans=0; inline void pushup(int x){mn[x]=min(mn[x<<1],mn[x<<1|1]);} inline void pushdown(int x){ mn[x<<1]+=add[x];mn[x<<1|1]+=add[x]; add[x<<1]+=add[x];add[x<<1|1]+=add[x]; add[x]=0; } void build(int v,int l,int r){ if(l==r){mn[v]=b[l];return;} int mid=l+r>>1; build(v<<1,l,mid);build(v<<1|1,mid+1,r); pushup(v); } void ins(int v,int l,int r,int x,int y){ if(x>y) return; if(x<=l&&r<=y){add[v]++;mn[v]++;return;} int mid=l+r>>1;pushdown(v); if(x<=mid) ins(v<<1,l,mid,x,y); if(mid<y) ins(v<<1|1,mid+1,r,x,y); pushup(v); } int query(int v,int l,int r,int x,int y){ if(x<=l && r<=y) return mn[v]; int mid=l+r>>1,s=inf;pushdown(v); if(x<=mid) s=min(s,query(v<<1,l,mid,x,y)); if(mid<y) s=min(s,query(v<<1|1,mid+1,r,x,y)); return s; } signed main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); int nn=unique(b+1,b+n+1)-b-1; build(1,1,nn); for(int i=1;i<=n;i++){ int p=lower_bound(b+1,b+nn+1,a[i])-b; ans+=query(1,1,nn,p,nn)-a[i]; ins(1,1,nn,1,p-1); } printf("%lld\n",ans); return 0; } ```