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


    传送门

    解题思路

      首先分块预处理,设(sum[i][j])为第(i)块到第(j)块的逆序对数量,(g[i][j])表示前(i)块数值(<=j)的数量,这两个东西是可以(O(nsqrt(n)log(n)))预处理出来的。询问的时候大块直接查询(sum),边角元素之间的贡献直接树状数组,边角元素与大块之间的贡献变成前缀和用(g)数组,时间复杂度(O(nsqrt(n)log(n)))

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    const int N=50005;
    const int M=300;
    
    inline int rd(){
    	int x=0,f=1; char ch=getchar();
    	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f?x:-x;	
    }
    
    int n,a[N],cpy[N],lstans,u,num,m,b[N];
    int sum[M][M],siz,bl[N],l[M],r[M],g[M][N];
    
    struct BIT{
    	int f[N];
    	inline void clear(){
    		memset(f,0,sizeof(f));	
    	}
    	inline void add(int x,int k){
    		for(;x<=u;x+=x&-x) f[x]+=k;	
    	}
    	inline int query(int x){
    		int ret=0;
    		for(;x;x-=x&-x) ret+=f[x];
    		return ret;	
    	}
    }tree;
    
    inline void prework(){
    	for(int i=1;i<=n;i++) g[bl[i]][a[i]]++;
    	for(int i=1;i<=num;i++) 
    		for(int j=1;j<=u;j++)
    			g[i][j]+=g[i][j-1];
    	for(int i=2;i<=num;i++)
    		for(int j=1;j<=u;j++)
    			g[i][j]+=g[i-1][j];
    	for(int i=1;i<=num;i++){
    		tree.clear();
    		for(int j=l[i];j<=n;j++){
    			sum[i][bl[j]]+=tree.query(u)-tree.query(a[j]);
    			tree.add(a[j],1);
    		}
    	}
    	for(int i=1;i<=num;i++)
    		for(int j=i+1;j<=num;j++)
    			sum[i][j]+=sum[i][j-1];
    }	
    
    inline int query(int x,int y){
    	tree.clear(); int ret=0;
    	if(bl[x]==bl[y]){
    		for(int i=x;i<=y;i++){
    			ret+=tree.query(u)-tree.query(a[i]);
    			tree.add(a[i],1);	
    		}
    		return ret;
    	}
    	ret=sum[bl[x]+1][bl[y]-1];
    	for(int i=x;i<=r[bl[x]];i++){
    		ret+=tree.query(u)-tree.query(a[i]);
    		if(bl[y]-1>bl[x]);
    		ret+=g[bl[y]-1][a[i]-1]-g[bl[x]][a[i]-1];
    		tree.add(a[i],1);
    	}
    	for(int i=l[bl[y]];i<=y;i++){
    		ret+=tree.query(u)-tree.query(a[i]);
    		if(bl[y]-1>bl[x]);
    		ret+=(g[bl[y]-1][u]-g[bl[x]][u])-(g[bl[y]-1][a[i]]-g[bl[x]][a[i]]);
    		tree.add(a[i],1);	
    	}
    	return ret;
    }
    
    int main(){
    	n=rd(); siz=sqrt(n)+1; num=n/siz; if(n%siz) num++;
    	for(int i=1;i<=n;i++) cpy[i]=a[i]=rd(),bl[i]=(i-1)/siz+1;
    	for(int i=1;i<=num;i++) l[i]=(i-1)*siz+1,r[i]=i*siz;
    	sort(cpy+1,cpy+1+n); u=unique(cpy+1,cpy+1+n)-cpy-1;
    	for(int i=1;i<=n;i++) a[i]=lower_bound(cpy+1,cpy+1+u,a[i])-cpy;
    	for(int i=1;i<=n;i++) b[i]=a[i]; 
    	r[num]=n; prework(); m=rd(); int l,r;
    	while(m--){
    		l=rd(),r=rd(); l^=lstans; r^=lstans;
    		lstans=query(l,r); printf("%d
    ",lstans);
    	}
    	return 0;	
    }
    
  • 相关阅读:
    MAIL (mailed 317 bytes of output but got status 0x004b#012)
    centOS7 复制文件夹
    X000100
    第一次博客作业
    《构建之法》阅读第四章、第十七章收获
    2016012017+小学四则运算练习软件项目报告
    看完构建之法1、2、16章的几个问题
    druid 多数据源配置
    flowableUI包
    vue 使用@fullcalendar进行行程展示
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10366870.html
Copyright © 2020-2023  润新知