zoukankan      html  css  js  c++  java
  • 【洛谷5046】[Ynoi2019 模拟赛] Yuno loves sqrt technology I(分块)

    点此看题面

    • 给定一个长度为(n)的序列,(q)次询问区间逆序对个数。
    • (n,qle10^5),强制在线

    不同部分答案的拆解

    根据分块套路,一个询问区间肯定会被拆成一个后缀散块+中间一段整块+一个前缀散块。

    考虑不同部分答案的预处理与计算。

    中间一段整块内部的答案:可以直接预处理出(ans_{i,j})表示编号(isim j)的块的总答案。

    左边的后缀散块和右边的前缀散块内部的答案:可以分别预处理出(pre_i)(suf_i)表示(i)的前缀散块和后缀散块的答案。

    左右散块与中间整块间的答案:直接枚举散块中的元素,询问中间比它大/小的数的个数,只需开一个前缀和计数数组(c_{i,j})表示前(i)个块大于等于(j)的数的出现次数总和。

    左右散块间的答案:事先将每个块排好序,枚举左边块中的每个元素,双指针维护右边块中比左边当前元素小的元素并统计在询问区间内的元素个数,然后若左边当前元素在询问区间内就更新答案。

    还有一种情况就是询问的(l,r)在一个块中,此时可以用前缀散块(r)的答案减去前缀散块(l-1)的答案再减去这两部分间的答案。其中最后那家伙和上面左右散块间答案的求法类似,只不过由于在同一个块中可以不使用双指针,直接扫一遍即可。

    预处理还是比较简单的,(pre_i)(suf_i)只要利用树状数组,(c_{i,j})直接一遍后缀和+一遍前缀和,(ans_{i,j})就在(ans_{i,j-1})基础上加入(j)中的元素利用(c_{i,j})算贡献。

    代码:(O(nsqrt n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define SN 600
    #define LL long long
    using namespace std;
    int n,a[N+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
    ');}
    }using namespace FastIO;
    struct TreeArray
    {
    	int a[N+5];I void U(RI x,CI v) {W(x<=n) a[x]+=v,x+=x&-x;}
    	I int Q(RI x,RI t=0) {W(x) t+=a[x],x-=x&-x;return t;}
    }T;
    I bool cmp(CI x,CI y) {return a[x]<a[y];}//按值排序
    int p[N+5],v[N+5],pre[N+5],suf[N+5];I void Build(CI L,CI R)//预处理块[L,R]的信息
    {
    	RI i;for(i=L;i<=R;++i) p[i]=i,v[i]=a[i];sort(p+L,p+R+1,cmp),sort(v+L,v+R+1);//事先给每个块中元素排好序
    	for(i=R;i>=L;--i) suf[i]=(i^R?suf[i+1]:0)+T.Q(a[i]),T.U(a[i],1);for(i=L;i<=R;++i) T.U(a[i],-1);//预处理每个后缀散块内部答案
    	for(i=L;i<=R;++i) pre[i]=(i^L?pre[i-1]:0)+(i-L-T.Q(a[i])),T.U(a[i],1);for(i=L;i<=R;++i) T.U(a[i],-1);//预处理每个前缀散块内部答案
    }
    int sz,bl[N+5],pl[SN+5],pr[SN+5],c[SN+5][N+5];LL ans[SN+5][SN+5];I void Init()//预处理
    {
    	RI i,j,k;for(sz=280,i=1;i<=n;++i) ++c[bl[i]=(i-1)/sz+1][a[i]],!pl[bl[i]]&&(pl[bl[i]]=i),pr[bl[i]]=i;//记录每个元素所在块,记录每个块左右端点
    	for(i=1;i<=bl[n];++i) {for(Build(pl[i],pr[i]),j=n;j;--j) c[i][j]+=c[i][j+1];for(j=1;j<=n;++j) c[i][j]+=c[i-1][j];}//计数数组,一遍前缀和+一遍前缀和
    	for(i=1;i<=bl[n];++i) for(ans[i][i]=pre[pr[i]],j=i+1;j<=bl[n];++j)
    		for(ans[i][j]=ans[i][j-1]+pre[pr[j]],k=pl[j];k<=pr[j];++k) ans[i][j]+=c[j-1][a[k]]-c[i-1][a[k]];//在之前基础上加入当前块中元素
    }
    I LL Q(CI l,CI r)//询问区间逆序对个数
    {
    	RI i,t=0,s=0,L=bl[l],R=bl[r];if(L==R)//同块
    	{
    		if(l==pl[L]) return pre[r];s=pre[r]-pre[l-1];for(i=pl[L];i<=pr[L];++i) p[i]<l?s-=t:p[i]<=r&&++t;return s;//直接扫一遍
    	}
    	int *c1=c[L],*c2=c[R-1];s=(pr[L]-l+1)*(R-L-1)*sz;
    	for(i=l;i<=pr[L];++i) s-=c2[a[i]]-c1[a[i]];for(i=pl[R];i<=r;++i) s+=c2[a[i]]-c1[a[i]];//散块与整块
    	int *PL=p+pl[L],*VL=v+pl[L],*EL=v+pr[L]+1,*PR=p+pl[R],*VR=v+pl[R],*ER=v+pr[R]+1;
    	for(;VL!=EL;*PL>=l&&(s+=t),++PL,++VL) W(VR!=ER&&*VL>*VR) *PR<=r&&++t,++PR,++VR;//散块与散块(双指针)
    	return suf[l]+ans[L+1][R-1]+pre[r]+s;//加上三部分各自的内部答案
    }
    int main()
    {
    	RI Qt,i;for(read(n,Qt),i=1;i<=n;++i) read(a[i]);
    	LL l,r,lst=0;Init();W(Qt--) read(l,r),writeln(lst=Q(l^lst,r^lst));return clear(),0;//强制在线
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    sonarque下载和安装使用
    npm install appium
    WIn10 电脑运行Docker
    AngularJs Type error : Cannot read property 'childNodes' of undefined
    Angular ui-route介绍
    Thymeleaf的模板使用介绍
    IntelliJ IDEA IDEA 2018 激活注册码
    session和cookies
    springmvc中的拦截器interceptor用法
    实现mapper接口注入的两种方式,以及后台的使用区别
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5046.html
Copyright © 2011-2022 走看看