[BZOJ3333]排队计划(离散化+树状数组+线段树)
来源:互联网 发布:桶装水管理软件 编辑:程序博客网 时间:2024/05/16 03:06
题目描述
传送门
题解
离散化。记高度为h。
首先用树状树组求出逆序对即为第一问的答案。
求出每个点后面有几个比它小记为rev[i],即为它对总逆序对数的贡献。建立线段树维护区间h的最小值。
对于每次询问的点P,不停地找区间[P,n]的最小值i,然后将h[i]赋为正无穷,直到点P的h为最小值停止。每次找到最小值的点都将ans减去那个点的rev。
这样做的基础是基于一个非常有用的性质:逆序对数只会不断减少,因为对于每一次操作,对于P前面的点没有影响,对于它后面的比P大的点也没有影响,而对于后面比它小的点,只有他们互相之间是有影响的,这个影响就是rev都变为0,即不会再产生后面的比它小的数了。
由于每个点只会被修改一次,那么均摊时间复杂度为O(nlogn)。
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define LL long longconst int max_n=5e5+5;const int max_tree=max_n*4;const int INF=2e9;int n,m,x,y,cnt,a[max_n],p[max_n],h[max_n];LL rev[max_n],ans,C[max_n];int tree[max_tree];inline int cmp(int x,int y){return a[x]<a[y];}inline void Bit_add(int loc,int val){ for (int i=loc;i<=cnt;i+=i&(-i)) C[i]+=val;}inline LL Bit_query(int loc){ LL ans=0; for (int i=loc;i>=1;i-=i&(-i)) ans+=(LL)C[i]; return ans;}inline void Segtree_update(int now){ if (h[tree[now<<1]]<h[tree[now<<1|1]]) tree[now]=tree[now<<1]; else tree[now]=tree[now<<1|1];}inline void Segtree_build(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ tree[now]=l; return; } Segtree_build(now<<1,l,mid); Segtree_build(now<<1|1,mid+1,r); Segtree_update(now);}inline void Segtree_change(int now,int l,int r,int x){ int mid=(l+r)>>1; if (l==r){ tree[now]=l; return; } if (x<=mid) Segtree_change(now<<1,l,mid,x); else Segtree_change(now<<1|1,mid+1,r,x); Segtree_update(now);}inline int Segtree_query(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=INF,anst; if (lrange<=l&&r<=rrange) return tree[now]; if (lrange<=mid){ int t=Segtree_query(now<<1,l,mid,lrange,rrange); if (ans>=h[t]) ans=h[t],anst=t; } if (mid+1<=rrange){ int t=Segtree_query(now<<1|1,mid+1,r,lrange,rrange); if (ans>=h[t]) ans=h[t],anst=t; } return anst;}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",&a[i]),p[i]=i; sort(p+1,p+n+1,cmp); for (int i=1;i<=n;++i) if (a[p[i]]!=a[p[i-1]]) h[p[i]]=++cnt; else h[p[i]]=cnt; for (int i=n;i>=1;--i) rev[i]=Bit_query(h[i]-1),ans+=rev[i],Bit_add(h[i],1); printf("%lld\n",ans); Segtree_build(1,1,n); for (int i=1;i<=m;++i){ scanf("%d",&x); while (h[x]!=INF){ y=Segtree_query(1,1,n,x,n); h[y]=INF; ans-=rev[y]; Segtree_change(1,1,n,y); } printf("%lld\n",ans); }}
总结
刚开始的思路好像有点对,但是想了一个树套树233
0 0
- [BZOJ3333]排队计划(离散化+树状数组+线段树)
- [bzoj3333][排队计划][树状数组+线段树]
- [BZOJ3333]排队计划(线段树)
- 【bzoj3333】排队计划 (线段树)
- bzoj 3333: 排队计划(树状数组+线段树)
- bzoj3333 排队计划
- BZOJ 3333 排队计划 树状数组+线段树
- BZOJ 3333: 排队计划 树状数组+线段树
- [树状数组 线段树] BZOJ 3333 排队计划
- bzoj 3333: 排队计划 树状数组+线段树
- BZOJ 3333: 排队计划 树状数组 线段树
- NOIP 2013 火柴排队 题解(离散化+树状数组)
- 离散化 + 线段树(树状数组) + 线扫描法
- codeforces Gym100589H Count Subarrays 树状数组/线段树+离散化
- hdu 5862 Counting Intersections 【线段树/树状数组+离散化】
- HDU5877 Weak Pair dfs + 线段树/树状数组 + 离散化
- [NOIP2013] 火柴排队 离散化 树状数组 逆序对
- 【求逆序对】CODE[VS] 3286 火柴排队 (树状数组离散化求逆序对)
- java字符串subString的实现
- python URL模块实例
- (Leetcode)5. Longest Palindromic Substring
- CSS3选择器详解二
- Bagging, Boosting, and Randomization对比
- [BZOJ3333]排队计划(离散化+树状数组+线段树)
- ios 微信分享,QQ分享,微博分享集成
- 第2章 分支出12章 第1章汇编概念
- UESTC 482 Charitable Exchange(优先队列+bfs)
- HDU 1166
- LoadRunner 问题总结
- target not be null
- Android笔记 Activity和Service的通信
- PowerDesigner使用之设计数据库