bzoj 4240: 有趣的家庭菜园
2018-03-14 22:05
218 查看
题意:
给出一个序列,问你最少交换多少次相邻的数,使这个序列变成单峰的。题解:
这题其实不难,但想了很久,关键是要想到怎么贪。考虑从小到达插入数,显然是向两边移,贪心取较小步数的是最优的大概意会下显然是对的那么可以树状数组为胡每个数当前位置。
注意相同的数要一起处理,wa了几发。
总结:
遇到这种序列题可以考虑按一定顺序插入。code:
#include<map> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define LL long long using namespace std; struct node{ int a,x; }h[300010]; int n,tr[300010],l=0,r=0; void change(int k,int c) {for(int i=k;i<=n;i+=i&-i) tr[i]+=c;} int get(int k) {int ans=0;for(int i=k;i>=1;i-=i&-i) ans+=tr[i];return ans;} bool cmp1(node a,node b) {return a.a==b.a?a.x<b.x:a.a<b.a;} bool cmp2(node a,node b) {return a.x>b.x;} LL ans=0; void solve(int L,int R) { while(L<=R) { int k=h[L].x+get(h[L].x); if(k-1-l<n-k-r-(R-L)) ans+=(LL)(k-1-l),l++,change(1,1),change(h[L].x,-1); else break; L++; } if(L<=R) { sort(h+L,h+R+1,cmp2); while(L<=R) { int k=h[L].x+get(h[L].x); ans+=(LL)(n-k-r);r++;change(h[L].x,-1);L++; } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&h[i].a),h[i].x=i; sort(h+1,h+n+1,cmp1); int p=1; while(p<=n) { int L=p; while(p<n&&h[p].a==h[p+1].a) p++; solve(L,p);p++; } printf("%lld",ans); }
相关文章推荐
- bzoj 4240: 有趣的家庭菜园【树状数组+贪心】
- bzoj 4240: 有趣的家庭菜园 树状数组+贪心
- [BZOJ]4240: 有趣的家庭菜园 贪心+树状数组
- BZOJ4240 有趣的家庭菜园(贪心+树状数组)
- [树状数组] BZOJ 4240 有趣的家庭菜园
- bzoj4240 有趣的家庭菜园 树状数组
- 【BZOJ4240】有趣的家庭菜园 树状数组+贪心
- [bzoj4240] 有趣的家庭菜园
- [BZOJ4240]有趣的家庭菜园(贪心+树状数组)
- BZOJ 4240 有趣的家庭菜园
- 【bzoj4240】有趣的家庭菜园
- BZOJ4240: 有趣的家庭菜园
- 【bzoj4240】有趣的家庭菜园 贪心+树状数组
- 4240: 有趣的家庭菜园
- 【OI做题记录】【BZOJ】有趣的家庭菜园
- JZOJ 4296【NOIP2015模拟11.2】有趣的有趣的家庭菜园
- 【NOIP2015模拟11.2】有趣的有趣的家庭菜园
- 【NOIP模拟题】【线段树】【离散化】【DP】2016.11.14第三题 有趣的有趣的家庭菜园 题解
- [JZOJ4296]有趣的有趣的家庭菜园
- ssoj2455有趣的有趣的家庭菜园(线段树)