• BZOJ 3787 Gty的文艺妹子序列(分块+树状数组+前缀和)


    题意

    给出n个数,要求支持单点修改和区间逆序对,强制在线。
    n,m<=50000

    题解

    和不带修改差不多,预处理出smaller[i][j]代表前i块小于j的数的数量,但不能用f[i][j]代表第i块到第j块逆序对的数量,这样不好维护。

    我们用f[i][j]代表从第i块选出一个元素与从第j块选出一个元素组成逆序对的数量,维护时最多修改根号n个f数组,查询时用前缀和起到与不带修改时f数组的作用。

    其他部分和不带修改时差不多。

    然后问题就解决了。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<algorithm>
      6 using namespace std;
      7 const int N=50100;
      8 int n,Block,a[N],block[N],L[300],R[300],tr1[300][300],tr[300][N],ans,m;
      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 void add1(int id,int x,int w){
     25     for(int i=x;i<=block[n];i+=lowbit(i)){
     26         tr1[id][i]+=w;
     27     }
     28 }
     29 int getsum1(int id,int x){
     30     int tmp=0;
     31     for(int i=x;i;i-=lowbit(i)){
     32         tmp+=tr1[id][i];
     33     }
     34     return tmp;
     35 }
     36 int main(){
     37     scanf("%d",&n);Block=sqrt(n);
     38     for(int i=1;i<=n;i++){
     39         scanf("%d",&a[i]);
     40         block[i]=(i-1)/Block+1;
     41         if(!L[block[i]])L[block[i]]=i;
     42         R[block[i]]=i;
     43     }
     44     for(int i=1;i<=block[n];i++)
     45         for(int j=L[i];j<=n;j++){
     46             add(i,a[j],1);
     47         }
     48     for(int i=1;i<=block[n];i++){
     49         for(int j=L[i];j<=R[i];j++){
     50             add(0,a[j],1);
     51             add1(i,i,getsum(0,n)-getsum(0,a[j]));
     52         }
     53         for(int j=R[i]+1;j<=n;j++){
     54             add1(i,block[j],getsum(0,n)-getsum(0,a[j]));
     55         }
     56         for(int j=L[i];j<=R[i];j++){
     57             add(0,a[j],-1);
     58         }
     59     }
     60     scanf("%d",&m);
     61     while(m--){
     62         int k,x,y;
     63         scanf("%d%d%d",&k,&x,&y);
     64         x^=ans;y^=ans;
     65         if(k==1){
     66             for(int i=1;i<=block[x]-1;i++){
     67                 int size=R[i]-L[i]+1;
     68                 add1(i,block[x],size-(getsum(i,y)-getsum(i+1,y))-(size-(getsum(i,a[x])-getsum(i+1,a[x]))));
     69             }
     70             for(int i=block[x]+1;i<=block[n];i++){
     71                 add1(block[x],i,getsum(i,y-1)-getsum(i+1,y-1)-(getsum(i,a[x]-1)-getsum(i+1,a[x]-1)));
     72             }
     73             for(int i=L[block[x]];i<=R[block[x]];i++){
     74                 add(0,a[i],1);
     75                 add1(block[x],block[x],-(getsum(0,n)-getsum(0,a[i])));
     76             }
     77             for(int i=L[block[x]];i<=R[block[x]];i++){
     78                 add(0,a[i],-1);
     79             }
     80             for(int i=1;i<=block[x];i++){
     81                 add(i,a[x],-1);add(i,y,1);
     82             }
     83             a[x]=y;
     84             for(int i=L[block[x]];i<=R[block[x]];i++){
     85                 add(0,a[i],1);
     86                 add1(block[x],block[x],getsum(0,n)-getsum(0,a[i]));
     87             }
     88             for(int i=L[block[x]];i<=R[block[x]];i++){
     89                 add(0,a[i],-1);
     90             }
     91         }
     92         else{
     93             if(block[x]+1>=block[y]){
     94                 ans=0;
     95                 for(int i=x;i<=y;i++){
     96                     add(0,a[i],1);
     97                     ans+=getsum(0,n)-getsum(0,a[i]);
     98                 }
     99                 for(int i=x;i<=y;i++){
    100                     add(0,a[i],-1);
    101                 }
    102                 printf("%d
    ",ans);
    103             }
    104             else{
    105                 ans=0;
    106                 for(int i=block[x]+1;i<=block[y]-1;i++){
    107                     ans+=getsum1(i,block[y]-1);
    108                 }
    109                 for(int i=x;i<=R[block[x]];i++){
    110                     add(0,a[i],1);
    111                     ans+=getsum(0,n)-getsum(0,a[i]);
    112                     ans+=getsum(block[x]+1,a[i]-1)-getsum(block[y],a[i]-1);
    113                 }
    114                 for(int i=L[block[y]];i<=y;i++){
    115                     add(0,a[i],1);
    116                     ans+=getsum(0,n)-getsum(0,a[i]);
    117                     ans+=getsum(block[x]+1,n)-getsum(block[y],n)-(getsum(block[x]+1,a[i])-getsum(block[y],a[i]));
    118                 }
    119                 for(int i=x;i<=R[block[x]];i++){
    120                     add(0,a[i],-1);
    121                 }
    122                 for(int i=L[block[y]];i<=y;i++){
    123                     add(0,a[i],-1);
    124                 }
    125                 printf("%d
    ",ans);
    126             }
    127         }
    128     }
    129     return 0;
    130 }
  • 相关阅读:
    [UML]UML系列——活动图activity diagram
    [UML]UML系列——包图Package
    UNIDAC不能识别CLIENTDATASET的TSINGLEFIELD
    UNIDAC如何驱动MSSQL2000
    delphi各个版本编译开关值
    优秀的数据序列和还原类----TSimpleMsgPack
    DELPHI方法注释的标准写法
    客户端如何通过咏南中间件调用存储过程和数据分页查询和文件传输的演示
    delphi 安卓程序如何读取外部配置文件
    调用DATASNAP+FIREDAC的远程方法有时会执行二次SQL或存储过程的BUG
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9499745.html
Copyright © 2020-2023  润新知