• BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)


    题面传送门

    题目大意:给你一个序列,多次询问,每次取出一段连续的子序列$[l,r]$,询问这段子序列的逆序对个数,强制在线

    很熟悉的分块套路啊,和很多可持久化01Trie的题目类似,用分块预处理出贡献,而这道题是用可持久化线段树罢了

    首先对序列分块,设块大小为$S$

    再建出主席树,我们就能在$O(logn)$时间内查询某个点$i$与区间$[l,r]$内的点产生的逆序对数量

    然后处理出点和整块之间的答案,设$f(i,j)$表示第$i$个点与第$j$块的开始/末尾这段区间内的点产生的逆序对数量。

    再根据 点到块的答案 统计出 块到块的答案

    对于每次询问,利用预处理出的东西$O(1)$搞出 整块到整块 的贡献,再暴力枚举边角+主席树查询搞出 边角到整块 和 边角到边角 的贡献。

    然后就会被卡常

    我们可以用树状数组搞出 边角到边角 的贡献,再用预处理的信息搞出 边角对整块 的贡献...

    虽然每次查询的时间也是$O(logn)$不变,但非递归的树状数组确实能减少大量的常数 #喷血

    分析一下时间复杂度,预处理+查询=O(nfrac{n}{S}logn+QSlogn),因为预处理是用主席树查询的所以比较慢..块要开大一些

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 50500
      6 #define M1 120
      7 #define ll long long 
      8 #define uint unsigned int 
      9 using namespace std;
     10 
     11 template <typename _T> void read(_T &ret)
     12 {
     13     ret=0; _T fh=1; char c=getchar();
     14     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
     15     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
     16     ret=ret*fh;
     17 }
     18 
     19 struct SEG{
     20 int ls[N1*20],rs[N1*20],sz[N1*20],root[N1],tot;
     21 void pushup(int rt){ sz[rt]=sz[ls[rt]]+sz[rs[rt]];  }
     22 void upd(int x,int l,int r,int rt1,int &rt2,int w)
     23 {
     24     if(!rt2||rt1==rt2){ rt2=++tot; ls[rt2]=ls[rt1]; rs[rt2]=rs[rt1]; sz[rt2]=sz[rt1]; }
     25     if(l==r){ sz[rt2]+=w; return; }
     26     int mid=(l+r)>>1;
     27     if(x<=mid) upd(x,l,mid,ls[rt1],ls[rt2],w);
     28     else upd(x,mid+1,r,rs[rt1],rs[rt2],w);
     29     pushup(rt2);
     30 }
     31 int query(int L,int R,int l,int r,int rt1,int rt2)
     32 {
     33     if(L<=l&&r<=R) return sz[rt2]-sz[rt1];
     34     int mid=(l+r)>>1,ans=0;
     35     if(L<=mid) ans+=query(L,R,l,mid,ls[rt1],ls[rt2]);
     36     if(R>mid) ans+=query(L,R,mid+1,r,rs[rt1],rs[rt2]);
     37     return ans;
     38 }
     39 }s;
     40 
     41 
     42 int n,m,sq,Q,de;
     43 
     44 struct BIT{
     45 int sum[N1];
     46 int upd(int x,int w)
     47 {
     48     int i;
     49     for(i=x;i<=m;i+=(i&(-i)))
     50         sum[i]+=w;
     51 }
     52 int query(int x)
     53 {
     54     if(!x) return 0; int i,ans=0; 
     55     for(i=x;i>0;i-=(i&(-i)))
     56         ans+=sum[i];
     57     return ans;
     58 }
     59 }bit;
     60 
     61 int a[N1],b[N1],pie[N1],st[M1],ed[M1];
     62 uint f[N1][M1],g[M1][M1];
     63 
     64 int main()
     65 {
     66     int i,j,k,l,r,q,x,y,px,py; uint ans=0;
     67     scanf("%d",&n);
     68     for(i=1;i<=n;i++) read(a[i]), b[i]=a[i];
     69     sort(b+1,b+n+1); m=unique(b+1,b+n+1)-(b+1);
     70     for(i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
     71     for(i=1;i<=n;i++) s.upd(a[i],1,m,s.root[i-1],s.root[i],1);
     72     
     73     sq=450;
     74     for(i=1;i<=n;i++) pie[i]=(i-1)/sq+1, ed[pie[i]]=i;
     75     for(i=1;i<=pie[n];i++) st[i]=(i-1)*sq+1;
     76     for(i=1;i<=n;i++)
     77     {
     78         if(a[i]<m)
     79         {
     80             for(j=1;j<pie[i];j++)
     81                 f[i][j]=s.query(a[i]+1,m,1,m,s.root[st[j]-1],s.root[i-1]);
     82             f[i][0]=s.query(a[i]+1,m,1,m,s.root[st[pie[i]]-1],s.root[i-1]);
     83         }
     84         if(a[i]>1)
     85         {
     86             for(j=pie[i];j<=pie[n];j++)
     87             {
     88                 f[i][j]=s.query(1,a[i]-1,1,m,s.root[i],s.root[ed[j]]);
     89                 g[pie[i]][j]+=f[i][j];
     90             }
     91         }
     92     }
     93     for(j=1;j<=pie[n];j++)
     94     for(i=1;i+j<=pie[n];i++)
     95         g[i][i+j]+=g[i+1][i+j];
     96     
     97     scanf("%d",&Q);
     98     for(q=1;q<=Q;q++)
     99     {
    100         read(x); read(y); x^=ans; y^=ans; ans=0; px=pie[x]; py=pie[y];
    101         if(px!=py){
    102             if(px+1<=py-1) ans=g[px+1][py-1];
    103             for(i=x;i<=ed[px];i++) ans+=f[i][py-1];
    104             if(px+1==py){ 
    105                 for(i=st[py];i<=y;i++) ans+=f[i][0];
    106             }else{ 
    107                 for(i=st[py];i<=y;i++) ans+=f[i][px+1]; 
    108             }
    109             for(i=st[py];i<=y;i++) bit.upd(a[i],1);
    110             for(i=x;i<=ed[px];i++) if(a[i]>1) ans+=bit.query(a[i]-1); 
    111             for(i=st[py];i<=y;i++) bit.upd(a[i],-1);
    112         }else{
    113             for(i=y;i>=x;i--) 
    114             {
    115                 if(a[i]>1) ans+=bit.query(a[i]-1);
    116                 bit.upd(a[i],1);
    117             }
    118             for(i=x;i<=y;i++) bit.upd(a[i],-1);
    119         }
    120         printf("%u
    ",ans);
    121     }
    122     return 0;
    123 }
  • 相关阅读:
    hdu 1214 圆桌会议(规律)
    hdu 1280 前m大的数
    hdu 2114 Calculate S(n)
    hdu 1210 Eddy's 洗牌问题
    hdu 1423 Greatest Common Increasing Subsequence(最长公共递增子序列lcis)
    7.30前端之Html简介
    8.3前端之Html列表
    7.30前端之Html头部
    7.30前端之Html元素
    7.23Java之递归练习
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10603552.html
Copyright © 2020-2023  润新知