BZOJ 2141 排队(分块+树状数组)

摘要:
,hn,依次指示初始队列中儿童的高度;第三行是正整数m,表示交换操作的次数;以下m行包含两个正整数ai和bi,表示交换位置ai和位置bi的子级。输出文件总共有m行,第i行中的一个正整数表示交换操作i后序列的混乱。1≤m≤2*10^3,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n

题意

第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi,表示交换位置ai与位置bi的小朋友。
输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度(逆序对数)。

1≤m≤2*10^3,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。

题解

难受,PE看成RE,下了数据手测20组发现没有问题,最后发现多了一个endl;

然后有重复但并不用去重。

分块做法
首先离散化,分块,对于每块建立一个树状数组,保存这个块中的所有元素
然后对于每个询问(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
然后对于块中的树状数组处理,块外的暴力
BZOJ 2141 排队(分块+树状数组)第1张

然后附上分块VSCDQ(上面的是分块)

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=21000;
 8 int n,a[N],b[N],block[N],Block,size[N],L[N],R[N],m,tr[500][N],ans;
 9 int lowbit(int x){
10     return x&-x;
11 }
12 void add(int id,int x,int w){
13     for(int i=x;i<=n;i+=lowbit(i)){
14         tr[id][i]+=w;
15     } 
16 }
17 int getsum(int id,int x){
18     int tmp=0;
19     for(int i=x;i;i-=lowbit(i)){
20         tmp+=tr[id][i];
21     }
22     return tmp;
23 }
24 int main(){
25 //    freopen("20.in","r",stdin);
26 //    freopen("xdx.out","w",stdout);
27     scanf("%d",&n);
28     Block=sqrt(n);
29     for(int i=1;i<=n;i++){
30         scanf("%d",&a[i]);
31         b[i]=a[i];
32         block[i]=(i-1)/Block+1;
33         size[block[i]]++;
34         if(!L[block[i]])L[block[i]]=i;
35         R[block[i]]=i;
36     }
37     sort(b+1,b+1+n);
38     int tot=unique(b+1,b+1+n)-b-1;
39     for(int i=1;i<=n;i++){
40         a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
41     }
42 //    cout<<endl;
43     for(int i=1;i<=n;i++){
44         add(block[i],a[i],1);
45     }
46     for(int i=n;i>=1;i--){
47         add(0,a[i],1);
48         ans+=getsum(0,a[i]-1);
49     }
50     scanf("%d",&m);
51     printf("%d
",ans);
52     for(int i=1;i<=m;i++){
53         int x,y;
54         scanf("%d%d",&x,&y);
55         if(x>y)swap(x,y);
56         if(block[x]+1>=block[y]){
57             for(int i=x+1;i<=y-1;i++){
58                 if(a[x]>a[i])ans--;if(a[x]<a[i])ans++;
59                 if(a[y]<a[i])ans--;if(a[y]>a[i])ans++;
60             }
61         }
62         else{
63             for(int i=block[x]+1;i<=block[y]-1;i++){
64                 ans-=getsum(i,a[x]-1)+size[i]-getsum(i,a[y]);
65                 ans+=getsum(i,a[y]-1)+size[i]-getsum(i,a[x]);
66             }
67             for(int i=x+1;i<=R[block[x]];i++){
68                 if(a[x]>a[i])ans--;if(a[x]<a[i])ans++;
69                 if(a[y]<a[i])ans--;if(a[y]>a[i])ans++;
70             }
71             for(int i=L[block[y]];i<=y-1;i++){
72                 if(a[x]>a[i])ans--;if(a[x]<a[i])ans++;
73                 if(a[y]<a[i])ans--;if(a[y]>a[i])ans++;
74             }
75         }
76         if(a[x]>a[y])ans--;
77         if(a[x]<a[y])ans++;
78         add(block[x],a[x],-1);add(block[x],a[y],1);
79         add(block[y],a[y],-1);add(block[y],a[x],1);
80         swap(a[x],a[y]);
81         printf("%d
",ans);
82     }
83     return 0;
84 }

免责声明:文章转载自《BZOJ 2141 排队(分块+树状数组)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇35 | 如何准备测试数据?Python文件读写、StringIO和BytesIO下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

HDU 1541.Stars-一维树状数组(详解)

树状数组,学长很早之前讲过,最近才重视起来,enmmmm。。。 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素...

hdu-3584 Cube---三维树状数组+区域更新单点查询

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3584 题目大意: 给定一个N*N*N多维数据集A,其元素是0或是1。A[i,j,k]表示集合中第 i 行,第 j 列与第 k 层的值。 首先由A[i,j,k] = 0(1 <= i,j,k <= N)。 给定两个操作: 1:改变A[i,j,k]为...

HDOJ 1166 敌兵布阵树状数组 线段树

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 18120Accepted Submission(s): 7877 Problem Description C国的死对头A国这段时间正在进行军事演习...

树状数组与线段树(一)

树状数组: 一共需要三个函数: ①lowbit(int x) ②add(int x,int p) ③query(int x) 1.动态求连续区间和 给定n个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列[a,b]的连续和。 输入格式 第一行包含两个整数n和m,分别表示数的个数和操作次数。 第二行包含n个整数,表示完整数列。 接下来m行,...

树状数组(转载)

树状数组是对一个数组改变某个元素和求和比较实用的数据结构。两中操作都是O(logn)。  在解题过程中,我们有时需要维护一个数组的前缀和S[i]=A[1]+A[2]+...+A[i]。           但是不难发现,如果我们修改了任意一个A[i],S[i]、S[i+1]...S[n]都会发生变化。           可以说,每次修改A[i]后,调整前...

树状数组基础

树状数组简介 如果有哪一种数据结构可以支持区间/单点和的更新和查询,一个显而易见的答案就是万能的线段树。但是线段树虽然能支持很多的区间问题,但是代码量有些长。如果我们只是单纯地为了维护区间和其实并不用去专门构建一棵线段树。树状数组作为一种更加简单的,可以维护区间和的数据结构应运而生。 树状数组基本思想 对于数组(A)来说,如果我们要求​Sum(Ai , A...