[bzoj]3295: [Cqoi2011]动态逆序对 主席树

来源:互联网 发布:阿里云丁丁 编辑:程序博客网 时间:2024/05/16 07:44

Description

对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

Input

输入第一行包含两个整数nm,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
 

Output

 
输出包含m行,依次为删除每个元素之前,逆序对的个数。

Sample Input

5 4
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)。

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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 板绘线条不流畅怎么办 嘴被风吹歪了怎么办 被风吹的嘴歪了怎么办 怀孕一个多月见红了怎么办 b本扣了6分怎么办 b牌驾驶证扣6分怎么办 忘记了谁考证的密码怎么办 专升本学校有课怎么办 跨境额度超了怎么办 微商代购被骗了怎么办 减肥到了瓶颈期该怎么办 大润发超市把一件商品打两件怎么办 小红书上买到假货怎么办 主动退市股票钱怎么办 老板卷款逃跑财务怎么办 房开延迟交房怎么办 房开逾期交房怎么办 买了保险想退保怎么办 辐射避难所探索废土死了怎么办 大门上边的齿轮滑丝怎么办 国通石油储油卡怎么办 买大棚房受骗了怎么办 朋友做安利天天来我门面怎么办 安利优惠顾客卡怎么办 苹果手机天气温度不显示怎么办? 安利净水器坏了怎么办 安利净水器滤芯盖搭配坏怎么办 安利会员卡过期了怎么办 婴儿吃了润唇膏怎么办? 用错沐浴露洗头怎么办 雅蜜润肤沐浴露怎么办 自煮小火锅水放少了怎么办 安利皇后锅发黑怎么办 宝宝灌肠后不拉屎怎么办 吃蛋白质粉肚子长胖了怎么办 安利产品过期了怎么办 拼多多拼不到人怎么办 被海南大宗骗了怎么办 手机被游戏扣钱怎么办 做酵素剩下的水果怎么办 喝了酵素胃疼怎么办