zoukankan      html  css  js  c++  java
  • [Ynoi2019模拟赛]Yuno loves sqrt technology II(二次离线莫队)

    二次离线莫队。

    终于懂了 (lxl) 大爷发明的二次离线莫队,(\%\%\%lxl)

    二次离线莫队,顾名思义就是将莫队离线两次。那怎么离线两次呢?

    每当我们将 ([l,r]) 移动右端点到 (a_{r+1}) 的时候,发现贡献为 ([1,r]-[1,l-1])(a_{r+1})

    ([1,r])(a_{r+1}) 的贡献可以 (O(nlog n)) 预处理出来,那么我们只需要处理 ([1,l-1])(a_{r+1}) 的贡献。

    那么我们将 ([l,r]) 移动右端点到 (r') 时,贡献多出来的只有 ([l,r])((r,r']) 的贡献。又由于前缀只有 (n) 个,所以我们可以再离线一下。

    因为总的区间移动长度由莫队的思想为 (O(nsqrt{n})),所以只需要一个 (O(sqrt{n})) 插入 (O(1)) 查询的数据结构。

    值域分块啊!

    那么我们算出来的其实是差分过的,其实一次询问的答案就是 (ans) 的前缀和。最后将原询问的位置找到就行了。

    鉴于上次的教训加了 (fread)(fwrite)。。。

    (Code Below:)

    #include <bits/stdc++.h>
    #define ll long long
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int maxn=100000+10;
    const int lim=100000;
    int n,m,blo,a[maxn],b[maxn],c[maxn],d[maxn],mp[maxn],tot;
    int pos[maxn],bL[maxn],bR[maxn];ll pre[maxn],suf[maxn],ans[maxn],out[maxn];
    
    namespace IO{
    	#define gc() (iS==iT?(iT=(iS=ibuff)+fread(ibuff,1,SIZ,stdin),(iS==iT?EOF:*iS++)):*iS++)
    	const int SIZ=1<<21|1;
    	char *iS,*iT,ibuff[SIZ],obuff[SIZ],*oS=obuff,*oT=oS+SIZ-1,fu[110],c;int fr;
    	inline void out(){
    		fwrite(obuff,1,oS-obuff,stdout);
    		oS=obuff;
    	}
    	template <class T>
    	inline void read(T &x){
    		x=0;T y=1;
    		for(c=gc();(c>'9'||c<'0')&&c!='-';c=gc());
    		c=='-'?y=-1:x=(c&15);
    		for(c=gc();c>='0'&&c<='9';c=gc()) x=x*10+(c&15);
    		x*=y;
    	}
    	template <class T>
    	inline void print(T x,char text='
    '){
    		if(x<0) *oS++='-',x*=-1;
    		if(x==0) *oS++='0';
    		while(x) fu[++fr]=x%10+'0',x/=10;
    		while(fr) *oS++=fu[fr--];
    		*oS++=text;out();
    	}
    }
    
    struct Query{
    	int l,r,v,id;
    }q[maxn];
    vector<Query> L[maxn],R[maxn];
    
    inline bool cmp(const Query &a,const Query &b){
    	if((a.l-1)/blo!=(b.l-1)/blo) return (a.l-1)/blo<(b.l-1)/blo;
    	return a.r<b.r;
    }
    
    inline void add(int x,int y){
    	for(;x<=n;x+=lowbit(x)) b[x]+=y;
    }
    
    inline int sum(int x){
    	int ans=0;
    	for(;x;x-=lowbit(x)) ans+=b[x];
    	return ans;
    }
    
    int main()
    {
    	IO::read(n);IO::read(m);blo=sqrt(n)+1;
    	for(int i=1;i<=n;i++) IO::read(a[i]),mp[i]=a[i];
    	sort(mp+1,mp+n+1);
    	tot=unique(mp+1,mp+n+1)-mp-1;
    	for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1,mp+tot+1,a[i])-mp;
    	for(int i=1;i<=n;i++) pre[i]=pre[i-1]+i-1-sum(a[i]),add(a[i],1);
    	memset(b,0,sizeof(b));
    	for(int i=n;i>=1;i--) suf[i]=suf[i+1]+sum(a[i]-1),add(a[i],1);
    	for(int i=1;i<=m;i++) IO::read(q[i].l),IO::read(q[i].r),q[i].id=i;
    	sort(q+1,q+m+1,cmp);q[0].l=1;
    	for(int i=1;i<=m;i++){
    		ans[i]=pre[q[i].r]-pre[q[i-1].r]+suf[q[i].l]-suf[q[i-1].l];
    		if(q[i-1].r<q[i].r) L[q[i-1].l-1].push_back((Query){q[i-1].r+1,q[i].r,-1,i});
    		if(q[i].r<q[i-1].r) L[q[i-1].l-1].push_back((Query){q[i].r+1,q[i-1].r,1,i});
    		if(q[i].l<q[i-1].l) R[q[i].r+1].push_back((Query){q[i].l,q[i-1].l-1,-1,i});
    		if(q[i-1].l<q[i].l) R[q[i].r+1].push_back((Query){q[i-1].l,q[i].l-1,1,i});
    	}
    	for(int i=1;i<=lim;i++){
    		pos[i]=(i-1)/blo+1;
    		if(pos[i]!=pos[i-1]) bL[pos[i]]=i,bR[pos[i-1]]=i-1;
    	}
    	bR[pos[lim]]=lim;
    	int sum,l,r,v,id;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<pos[a[i]];j++) c[j]++;
    		for(int j=bL[pos[a[i]]];j<=a[i];j++) d[j]++;
    		for(int j=0,siz=L[i].size();j<siz;j++){
    			l=L[i][j].l;r=L[i][j].r;v=L[i][j].v;id=L[i][j].id;sum=0;
    			for(int k=l;k<=r;k++) sum+=c[pos[a[k]+1]]+d[a[k]+1];
    			ans[id]+=v*sum;
    		}
    	}
    	memset(c,0,sizeof(c));
    	memset(d,0,sizeof(d));
    	for(int i=n;i>=1;i--){
    		for(int j=pos[a[i]]+1;j<=blo;j++) c[j]++;
    		for(int j=a[i];j<=bR[pos[a[i]]];j++) d[j]++;
    		for(int j=0,siz=R[i].size();j<siz;j++){
    			l=R[i][j].l;r=R[i][j].r;v=R[i][j].v;id=R[i][j].id;sum=0;
    			for(int k=l;k<=r;k++) sum+=c[pos[a[k]-1]]+d[a[k]-1];
    			ans[id]+=v*sum;
    		}
    	}
    	for(int i=1;i<=m;i++) ans[i]+=ans[i-1],out[q[i].id]=ans[i];
    	for(int i=1;i<=m;i++) IO::print(out[i]);
    	return 0;
    }
    
  • 相关阅读:
    DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践
    UVA10071 Back to High School Physics
    UVA10071 Back to High School Physics
    UVA10055 Hashmat the Brave Warrior
    UVA10055 Hashmat the Brave Warrior
    UVA458 The Decoder
    UVA458 The Decoder
    HDU2054 A == B ?
    HDU2054 A == B ?
    POJ3414 Pots
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/10350967.html
Copyright © 2011-2022 走看看