zoukankan      html  css  js  c++  java
  • BZOJ 2141 排队(分块+树状数组)

    题意

    第一行为一个正整数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
    然后对于块中的树状数组处理,块外的暴力

    然后附上分块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 }
  • 相关阅读:
    理解构造器
    if与switch的性能比较
    Java对象的内存(一)
    shell编程_条件判断if
    shell编程_基础&变量
    集群架构篇:Nginx架构演进<拆分数据库 多台web节点共享静态资源>
    集群架构篇:Nginx流行架构LNMP
    集群架构篇:Nginx常用模块
    LInux系统@安装CentOS7虚拟机
    docker pull越来越慢的解决方法
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9495130.html
Copyright © 2011-2022 走看看