Bzoj 2141: 排队 分块,逆序对,树状数组

Posted 微弱的世界

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj 2141: 排队 分块,逆序对,树状数组相关的知识,希望对你有一定的参考价值。

2141: 排队

Time Limit: 4 Sec  Memory Limit: 259 MB
Submit: 1310  Solved: 517
[Submit][Status][Discuss]

Description

排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。

Input

第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi¬,表示交换位置ai与位置bi的小朋友。

Output

输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。

Sample Input

【样例输入】
3
130 150 140
2
2 3
1 3

Sample Output

1
0
3
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足i<j且hi>hj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
【数据规模和约定】
对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。

HINT

 

Source

 题解:
分块+树状数组+逆序对
过了一道国家队的题,好开心。
而且还发现了以前求逆序对数的错误。幸好不是考试。
老是在小错误上马虎。。。QAQ
 
可以发现对于每个询问和变换[l,r],只有(l,r)有影响,两端并没有影响。
所以我们每次修改只用去变中间的部分。
首先,先求出初始数列逆序对的数目。
然后,用分块将每一块内排序。
之后,对于每个询问,我们去计算变化量。
然后输出即可。。。
*******************Orz???金牌爷??***************************

给定一个序列,m次交换两个数,求初始逆序对数及每次交换后的逆序对数

首先离散化,分块,对于每块建立一个树状数组,保存这个块中的所有元素

然后对于每个询问(x,y) (x<y) 两侧的数是没有影响的,区间(x,y)的数a[i]讨论如下

a[i]<a[x] --ans

a[i]>a[x] ++ans

a[i]<a[y] ++ans

a[i]>a[y] --ans

然后对于块中的树状数组处理,块外的暴力

注意此题元素有重复 亲测可信

RANK5吓尿0.0 为何块套树要比树套树还快……

                                                                     ------摘自Popoqqq

*********************************************************

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 20010
  4 int block,a[MAXN],b[MAXN],BIT[MAXN],pos[MAXN],ans,tot,n;
  5 int read()
  6 {
  7     int s=0,fh=1;char ch=getchar();
  8     while(ch<0||ch>9){if(ch==-)fh=-1;ch=getchar();}
  9     while(ch>=0&&ch<=9){s=s*10+(ch-0);ch=getchar();}
 10     return s*fh;
 11 }
 12 int Lowbit(int o){return o&(-o);}
 13 void Update(int o,int o1)
 14 {
 15     while(o<=tot)
 16     {
 17         BIT[o]+=o1;
 18         o+=Lowbit(o);
 19     }
 20 }
 21 int Sum(int o)
 22 {
 23     int sum=0;
 24     while(o>0)
 25     {
 26         sum+=BIT[o];
 27         o-=Lowbit(o);
 28     }
 29     return sum;
 30 }
 31 void cl(int k)
 32 {
 33     int l=(k-1)*block+1,r=min(k*block,n),i;
 34     for(i=l;i<=r;i++)b[i]=a[i];
 35     sort(b+l,b+r+1);
 36 }
 37 int Find(int l,int r,int find1)
 38 {
 39     int mid,ll=l,get=0;
 40     while(l<=r)
 41     {
 42         mid=(l+r)/2;
 43         if(b[mid]<find1){get=mid;l=mid+1;}
 44         else r=mid-1;
 45     }
 46     if(get==0)return 0;
 47     return (get-ll+1);
 48 }
 49 int Find1(int l,int r,int find1)
 50 {
 51     int mid,rr=r,get=0;
 52     while(l<=r)
 53     {
 54         mid=(l+r)/2;
 55         if(b[mid]>find1){get=mid;r=mid-1;}
 56         else l=mid+1;
 57     }
 58     if(get==0)return 0;
 59     return (rr-get+1);
 60 }
 61 void calc(int l,int r)
 62 {
 63     int L=pos[l],R=pos[r],i,gs,gs1;
 64     if(a[l]>a[r])ans--;
 65     if(a[l]<a[r])ans++;
 66     if(L==R)
 67     {
 68         for(i=l+1;i<=r-1;i++)
 69         {
 70             if(a[i]>a[l])ans++;
 71             if(a[i]<a[l])ans--;
 72             if(a[i]>a[r])ans--;
 73             if(a[i]<a[r])ans++;
 74         }
 75         swap(a[l],a[r]);
 76         cl(L);cl(R);
 77         return;
 78     }
 79     for(i=l+1;i<=L*block;i++)
 80     {
 81         if(a[i]>a[l])ans++;
 82         if(a[i]<a[l])ans--;
 83         if(a[i]>a[r])ans--;
 84         if(a[i]<a[r])ans++;
 85     }
 86     for(i=L+1;i<=R-1;i++)
 87     {
 88         gs=Find((i-1)*block+1,min(i*block,n),a[l]);
 89         ans-=gs;
 90         gs1=Find((i-1)*block+1,min(i*block,n),a[r]);
 91         ans+=gs1;
 92         gs=Find1((i-1)*block+1,min(i*block,n),a[l]);
 93         ans+=gs;
 94         gs1=Find1((i-1)*block+1,min(i*block,n),a[r]);
 95         ans-=gs1;
 96     }
 97     for(i=(R-1)*block+1;i<=r-1;i++)
 98     {
 99         if(a[i]>a[l])ans++;
100         if(a[i]<a[l])ans--;
101         if(a[i]>a[r])ans--;
102         if(a[i]<a[r])ans++;
103     }
104     swap(a[l],a[r]);
105     cl(L);cl(R);
106 }
107 int main()
108 {
109     freopen("nt2011_queue.in","r",stdin);
110     freopen("nt2011_queue.out","w",stdout);
111     int i,ai,bi,m,M,wz;
112     n=read();
113     block=(int)sqrt(n);
114     for(i=1;i<=n;i++)a[i]=read(),b[i]=a[i];
115     sort(b+1,b+n+1);
116     tot=unique(b+1,b+n+1)-(b+1);
117     memset(BIT,0,sizeof(BIT));
118     //for(i=1;i<=tot;i++)Update(i,1);
119     ans=0;
120     for(i=n;i>=1;i--)
121     {
122         wz=lower_bound(b+1,b+tot+1,a[i])-b;
123         ans+=Sum(wz-1);
124         Update(wz,1);
125         a[i]=wz;
126     }
127     /*for(i=1;i<=n;i++)
128     {
129         a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
130         ans+=Sum(a[i]-1);
131         if(BIT[a[i]]!=0)Update(a[i],-1);
132     }*/
133     printf("%d\n",ans);
134     for(i=1;i<=n;i++)pos[i]=(int)(i-1)/block+1;
135     if(n%block==0)M=n/block;
136     else M=n/block+1;
137     for(i=1;i<=M;i++)cl(i);
138     m=read();
139     for(i=1;i<=m;i++)
140     {
141         ai=read();bi=read();
142         if(ai>bi)swap(ai,bi);
143         calc(ai,bi);
144         printf("%d\n",ans);
145     }
146     fclose(stdin);
147     fclose(stdout);
148     return 0;
149 }

 

以上是关于Bzoj 2141: 排队 分块,逆序对,树状数组的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2141 排队(块套树,分块,树状数组)BZOJ修复工程

BZOJ 2141 排队(块套树,分块,树状数组)BZOJ修复工程

[BZOJ 2141][国家集训队 2011]排队 树状数组套平衡树

bzoj2141_排队

bzoj 2141: 排队

BZOJ 3333 排队计划 树状数组+线段树