[bzoj]3295: [Cqoi2011]动态逆序对 主席树
来源:互联网 发布:阿里云丁丁 编辑:程序博客网 时间:2024/05/16 07:44
Description
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
Input
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
Output
输出包含m行,依次为删除每个元素之前,逆序对的个数。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
HINT
N<=100000 M<=50000
玩个蛋,高高兴兴写了个主席树,MLE到死,最后发现要优化才行。
因为n>m,所以我们得考虑将nlognlogn搞成mlognlogn,特别蛋疼。
对于原序列,建议棵主席树(不带修改的那种,重复使用信息的),然后对于后来修改的,再建一棵主席树,蛋疼。
这题就是询问1---x-1,x+1---n,分别有多少个大于他与小于他的个数,维护一下就是了。
萎靡的主席树(我要写分块儿!!)
#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<ctime>using namespace std;#define MAX_N 208500typedef long long LL;LL bit[MAX_N];LL ans=0;int n,m;int bel[MAX_N];void addans(int x){for (;x<=n;x+=x&(-x)) bit[x]++;}LL getans(int x){LL ret=0;for (;x>=1;x-=x&(-x)) ret+=bit[x];return ret;}int lc[MAX_N*45],rc[MAX_N*45],root[MAX_N*45],sum[MAX_N*45];int tal=0;void updata(int k){sum[k]=sum[lc[k]]+sum[rc[k]];}void add(int &k,int l,int r,int x,int v){if (!k) k=++tal;if (l==r){sum[k]+=v;return;}int mid=(l+r)/2;if (x<=mid)add(lc[k],l,mid,x,v);else add(rc[k],mid+1,r,x,v);updata(k);}int v1[MAX_N/2],v2[MAX_N/2],tp1,tp2;LL querymore(int l,int r,int x){LL ret=0;while (l<r){int mid=(l+r)/2;if (mid+1<=x){for (int k=1;k<=tp1;k++) v1[k]=rc[v1[k]];for (int k=1;k<=tp2;k++) v2[k]=rc[v2[k]];l=mid+1;}else{for (int k=1;k<=tp1;k++) ret-=sum[rc[v1[k]]];for (int k=1;k<=tp2;k++) ret+=sum[rc[v2[k]]];for (int k=1;k<=tp1;k++) v1[k]=lc[v1[k]];for (int k=1;k<=tp2;k++) v2[k]=lc[v2[k]];r=mid;}//printf("L:%d R:%d ret:%d x:%d\n",l,r,ret,x);}return ret;}LL queryless(int l,int r,int x){LL ret=0;while (l<r){int mid=(l+r)/2;if (mid+1<=x){for (int k=1;k<=tp1;k++) ret-=sum[lc[v1[k]]];for (int k=1;k<=tp2;k++) ret+=sum[lc[v2[k]]];for (int k=1;k<=tp1;k++) v1[k]=rc[v1[k]];for (int k=1;k<=tp2;k++) v2[k]=rc[v2[k]];l=mid+1;}else{for (int k=1;k<=tp1;k++) v1[k]=lc[v1[k]];for (int k=1;k<=tp2;k++) v2[k]=lc[v2[k]];r=mid;}//printf("L:%d R:%d ret:%d x:%d\n",l,r,ret,x);}return ret;}int main(){freopen("3295.in","r",stdin);freopen("3295.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){//树状数组->总共_逆序对 int x;scanf("%d",&x);ans+=getans(n)-getans(x);addans(x);bel[x]=i;for (int k=i;k<=n;k+=k&(-k))add(root[k],1,n,x,1);}//printf("ans:%d",ans);for (int i=1;i<=m;i++){printf("%I64d\n",ans);int x;scanf("%d",&x);int L,R;LL ret1=0,ret2=0;L=1;R=bel[x];//K大 tp1=0;tp2=0;for (int k=L-1;k>=1;k-=k&(-k))v1[++tp1]=root[k];for (int k=R;k>=1;k-=k&(-k))v2[++tp2]=root[k];ret1+=querymore(1,n,x);L=bel[x];R=n;tp1=0;tp2=0;for (int k=L-1;k>=1;k-=k&(-k))v1[++tp1]=root[k];for (int k=R;k>=1;k-=k&(-k))v2[++tp2]=root[k];ret2+=queryless(1,n,x);for (int k=bel[x];k<=n;k+=k&(-k))add(root[k],1,n,x,-1);//printf("x:%d more:%d less:%d\n",x,ret1,ret2);ans-=ret1+ret2;}return 0;}
3 0
- [bzoj]3295: [Cqoi2011]动态逆序对 主席树
- 主席树初探 & bzoj 3295: [Cqoi2011] 动态逆序对 题解
- BZOJ 3295: [Cqoi2011]动态逆序对 (树状数组套主席树)
- 3295: [Cqoi2011]动态逆序对 树状数组套主席树
- [BZOJ 3295] Cqoi2011 动态逆序对
- 【BZOJ 3295】 [Cqoi2011]动态逆序对
- BZOJ 3295 [Cqoi2011]动态逆序对
- BZOJ 3295 [CQOI2011] 动态逆序对
- BZOJ 3295: [Cqoi2011]动态逆序对
- 【BZOJ 3295】[Cqoi2011]动态逆序对
- bzoj 3295 [Cqoi2011]动态逆序对
- BZOJ 3295 [Cqoi2011]动态逆序对
- 【BZOJ】3295 [Cqoi2011]动态逆序对 树状数组+线段树
- 【bzoj3295】 CQOI2011动态逆序对 树状数组+主席树
- 【bzoj3295】[Cqoi2011]动态逆序对 树状数组套主席树
- bzoj 3295: [Cqoi2011]动态逆序对(树套树)
- bzoj 3295: [Cqoi2011]动态逆序对 【cdq分治】
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
- 指针访问方式从键盘给数组 a[N]输入数据, 然后对元素值重新按逆序存放并输出
- Ubuntu安装配置Mysql
- Binary Search Tree vs Hash Table?
- 大家来说说大数据时代与真正跨平台应用,如何结合的更好
- JS Tab切换 选项卡 五种方法
- [bzoj]3295: [Cqoi2011]动态逆序对 主席树
- POJ-2262-Goldbach's Conjecture-2013-11-28 23:15:10
- 高效网站开发缓存技术应用——网页输出缓存(Ⅰ)
- Android实现推送方式解决方案
- Android NDK的include配置
- JAVA WEB项目の问题汇总
- POJ-3006-Dirichlet's Theorem on Arithmetic Progressions-2013-12-02 18:05:36
- html radio
- 【踩雷】android 中UI线程内调用gl指令的结果