zoukankan      html  css  js  c++  java
  • BZOJ3787 : Gty的文艺妹子序列

    将序列分成$sqrt{n}$块,预处理出每两块之间的逆序对数,以及ap[i]表示前i块内数字出现次数的树状数组

    预处理:$O(nsqrt{n}log n)$

    修改时,ap[i]可以在$O(sqrt{n}log n)$复杂度内完成修改,然后考虑修改的位置对答案的贡献,可以发现相当于某一行、某一列都加上一个数,对于行列各开$sqrt{n}$棵树状数组差分维护

    修改:$O(sqrt{n}log n)$

    查询时中间那块可以通过树状数组$O(log n)$求出,然后向两边暴力扩展

    查询:$O(sqrt{n}log n)$

    #include<cstdio>
    const int N=50010,K=230;
    int n,m,op,l,r,i,j,k,size,block,a[N],pos[N],st[K],en[K],ans[K][K],T,x,y,z,now,all,last,tmp[K][2],ap[K][N],tag[2][K][K],bit[N],vis[N];
    inline void read(int&a){char ch;while(!(((ch=getchar())>='0')&&(ch<='9')));a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))(a*=10)+=ch-'0';}
    inline void add(int x){for(;x<=n;x+=x&-x)if(vis[x]!=T)vis[x]=T,bit[x]=1;else bit[x]++;}
    inline int sum(int x){int t=0;for(;x;x-=x&-x)if(vis[x]==T)t+=bit[x];return t;}
    inline void add(int p,int x,int y){for(;x<=n;x+=x&-x)ap[p][x]+=y;}
    inline int sum(int p,int x){if(!p)return 0;int t=0;for(;x;x-=x&-x)t+=ap[p][x];return t;}
    inline void add(int w,int p,int x,int y){for(;x<=block;x+=x&-x)tag[w][p][x]+=y;}
    inline int sum(int w,int p,int x){int t=0;for(;x;x-=x&-x)t+=tag[w][p][x];return t;}
    inline void change(int x,int y){
      z=a[x];
      for(i=k=pos[x];i<=block;i++)add(i,z,-1),add(i,y,1);
      now=sum(k-1,z)-sum(k-1,y)+sum(k,z-1)-sum(k,y-1);
      for(i=st[k];i<x;i++){
        if(a[i]>z)now--;
        if(a[i]>y)now++;
      }
      for(i=en[k];i>x;i--){
        if(a[i]<z)now--;
        if(a[i]<y)now++;
      }
      for(i=1;i<=block;i++)tmp[i][0]=sum(i-1,y)-sum(i-1,z),tmp[i][1]=sum(i,y-1)-sum(i,z-1);
      for(i=k;i;i--)add(0,i,k,now+tmp[i][0]);
      for(i=k;i<=block;i++)add(1,i,1,tmp[i][1]),add(1,i,k+1,-tmp[i][1]);
      a[x]=y;
    }
    inline int ask(int l,int r){
      T++,x=pos[l],y=pos[r];
      if(x==y){
        now=0;
        for(;r>=l;r--)now+=sum(a[r]-1),add(a[r]);
        return now;
      }
      now=ans[x+1][y-1]+sum(0,x+1,y-1)+sum(1,y-1,x+1),all=st[y]-en[x]-1;
      for(i=st[y];i<=r;i++)now+=all-sum(a[i])-sum(y-1,a[i])+sum(x,a[i]),add(a[i]),all++;
      for(i=en[x];i>=l;i--)now+=sum(a[i]-1)+sum(y-1,a[i]-1)-sum(x,a[i]-1),add(a[i]);
      return now;
    }
    int main(){
      read(n);
      for(i=1;i<=n;i++)read(a[i]);
      for(;size*size<n;size++);
      for(i=1;i<=n;i++)pos[i]=(i-1)/size+1;
      for(block=pos[n],i=1;i<=block;i++)st[i]=size*(i-1)+1;
      for(en[block]=n,i=block-1;i;i--)en[i]=st[i+1]-1;
      for(i=1;i<=block;i++){
        now=all=0,T++;
        for(j=1;j<=n;j++)ap[i][j]=ap[i-1][j];
        for(j=st[i];j<=en[i];j++)add(i,a[j],1);
        for(j=i;j<=block;ans[i][j++]=now)for(k=st[j];k<=en[j];k++)now+=all-sum(a[k]),add(a[k]),all++;
      }
      read(m);
      while(m--){
        read(op),read(l),read(r),l^=last,r^=last;
        if(!op)printf("%d
    ",last=ask(l,r));else change(l,r);
      }
      return 0;
    }
    

      

  • 相关阅读:
    NX二次开发-Block UI C++界面Body Collector(体收集器)控件的获取(持续补充)
    NX二次开发-Block UI C++界面(表达式)控件的获取(持续补充)
    NX二次开发-常用lib库文件
    NX二次开发-如何在类外面定义一个结构体
    NX二次开发-bat脚本文件切换NX的环境变量(NX路径和语言)
    NX二次开发-相对路径环境变量和绝对路径环境变量
    NX二次开发-UFUN所有对象类型的宏定义
    NX二次开发-UFUN创建球UF_MODL_create_sphere1
    NX二次开发-UFUN获取球的参数UF_MODL_ask_sphere_parms
    NX二次开发-UFUN获取块的参数UF_MODL_ask_block_parms
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403194.html
Copyright © 2011-2022 走看看