BZOJ 4240 有趣的家庭菜园
第一道树状数组
用到了贪心的想法
交换的代价就是交换完之后的逆序对数
将所有IOI草从高到低放入
贪心判断是放在左边还是放在右边
会爆int
也要考虑有两棵IOI草高度相同
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int MAXN=300005; inline int read(){ int x=0,f=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,data[MAXN]; inline void add(int x,int i){ while(x<=n) data[x]+=i,x+=x&(-x); } inline int query(int x){ int res=0; while(x) res+=data[x],x-=x&(-x); return res; } int id[MAXN],a[MAXN]; inline int cmp(int x,int y){ return a[x]>a[y]; } inline int cal(int x,int num){ int res=query(x); if(res*2>=num) res=num-res; // cout<<res<<endl; return res; } int main(){ n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) id[i]=i; sort(id+1,id+1+n,cmp); long long ans=0; for(int i=1;i<=n;i++){ int k=i; while(k<n&&a[id[k]]==a[id[k+1]]) ans+=cal(id[k],i-1),k++; ans+=cal(id[k],i-1); // cout<<k<<endl; // cout<<ans<<endl; for(int j=i;j<=k;j++) add(id[j],1); i=k; } printf("%lld\n",ans); return 0; }