zoukankan      html  css  js  c++  java
  • 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;	
    }
    
  • 相关阅读:
    《Expert .NET 2.0 IL Assembler》 译者笔记 2
    游戏大厅升级日记 第2天
    《Metadata Tables》 Authors
    随便写写,蛮有趣的
    《Metadata Tables》 Introduction
    Oracle跨数据库的数据操作
    要换工作环境了
    javascript中几种操作打印的方法
    Datagrid中实现单选功能
    C#中利用Oracle事务删除表
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10366870.html
Copyright © 2011-2022 走看看