zoukankan      html  css  js  c++  java
  • BZOJ3787 Gty的文艺妹子序列

    Gty的文艺妹子序列

    给定一个正整数序列a(1<=ai<=n),支持单点修改,对于每次询问,输出al...ar中的逆序对数,强制在线。

    分析

    由于强制在线,考虑分块。

    (ans(i,j))表示在第(i)块取一个元素并在第(j)块取一个元素组成的逆序对个数。 那么每次修改操作会涉及到根号个值发生改变,询问操作时需要对第二维进行区间查询。因此第二维用树状数组维护。

    (sum(i,j))表示前(i)块元素(j)的个数,那么修改操作也只会改变根号个值,询问操作需要对第二维进行区间查询,因此第二维用树状数组维护。

    (num(i))表示第(i)块内逆序对个数,修改操作暴力重算。

    分步讨论

    设块的大小为(S).

    初始化

    (ans)枚举块对,左边计入树状数组,右边统计逆序对,时间复杂度(O((frac{N}{S})^2 cdot S log N)=O(frac{N^2}{S} cdot log N))

    (sum)枚举块,用树状数组统计逆序对,复杂度(O(frac{N}{S} cdot N cdot log N)=O(frac{N^2}{S} cdot log N))

    (num)直接树状数组,复杂度(O(frac{N}{S} cdot S cdot log N)=O(N log N))

    总复杂度(O(frac{N^2}{S} cdot log N))

    区间查询

    1. L,R在距离小于2的块内,直接树状数组统计,复杂度(O(S cdot log N))

    2. L,R在距离大于等于2的块内,中间块用ans计算,两边的用树状数组和sum计算,复杂度(O(frac{N}{S} cdot log frac{N}{S}+S cdot log N))

    总复杂度(O(frac{N}{S} cdot log frac{N}{S}+S cdot log N))

    单点修改

    (ans)利用(sum)修改,复杂度(O(frac{N}{S} cdot log N))

    (sum)直接修改,复杂度(O(frac{N}{S} cdot log N))

    (num)直接修改,复杂度(O(S cdot log N))

    总复杂度(O(frac{N}{S} cdot log N+S cdot log N))

    总复杂度

    [O(frac{N^2}{S} cdot log N+M cdot (frac{N}{S} cdot log N+S cdot log N)) ]

    由于(M,N)同阶

    [=O(frac{N^2}{S} cdot log N + N cdot S cdot log N) geq O(n^{frac{3}{2}} cdot log N) ]

    当两项相等时,取等号,而此时

    [S=O(sqrt{n}) ]

    const int MAXN=5e4+7,MAXB=250;
    
    int n,m,blo;
    int bl[MAXN],a[MAXN];
    int tree[MAXN];
    int ans[MAXB][MAXB],sum[MAXB][MAXN],num[MAXB];
    
    int lowbit(int x)
    {
    	return x&-x;
    }
    
    void change(int p,int v) // tree
    {
    	while(p<=n)
    	{
    		tree[p]+=v;
    		p+=lowbit(p);
    	}
    }
    
    int query(int p)
    {
    	int res=0;
    	while(p)
    	{
    		res+=tree[p];
    		p-=lowbit(p);
    	}
    	return res;
    }
    
    void change2(int id,int p,int v) // ans
    {
    	while(p<=bl[n])
    	{
    		ans[id][p]+=v;
    		p+=lowbit(p);
    	}
    }
    
    int query2(int id,int p)
    {
    	int res=0;
    	while(p)
    	{
    		res+=ans[id][p];
    		p-=lowbit(p);
    	}
    	return res;
    }
    
    void change3(int id,int p,int v) // sum
    {
    	while(p<=n)
    	{
    		sum[id][p]+=v;
    		p+=lowbit(p);
    	}
    }
    
    int query3(int id,int p)
    {
    	int res=0;
    	while(p)
    	{
    		res+=sum[id][p];
    		p-=lowbit(p);
    	}
    	return res;
    }
    
    int main()
    {
    //  freopen(".in","r",stdin);
    //  freopen(".out","w",stdout);
    	read(n);
    	blo=sqrt(n);
    	for(int i=1;i<=n;++i)
    	{
    		read(a[i]);
    		bl[i]=(i-1)/blo+1; // belong
    	}
    	for(int i=1;i<bl[n];++i)
    	{
    		for(int j=(i-1)*blo+1;j<=i*blo;++j)
    			change(a[j],1);
    		for(int j=i+1;j<=bl[n];++j) // cal ans(i,j)
    		{
    			int t=0;
    			for(int k=(j-1)*blo+1;k<=min(j*blo,n);++k)
    				t+=query(n)-query(a[k]);
    			change2(i,j,t);
    		}
    		for(int j=(i-1)*blo+1;j<=i*blo;++j)
    			change(a[j],-1);
    	}
    	for(int i=1;i<=bl[n];++i) // cal sum(i,)
    		for(int j=1;j<=min(i*blo,n);++j)
    			change3(i,a[j],1);
    	for(int i=1;i<=bl[n];++i) // cal num(i)
    	{
    		for(int j=(i-1)*blo+1;j<=min(i*blo,n);++j)
    		{
    			num[i]+=query(n)-query(a[j]);
    			change(a[j],1);
    		}
    		for(int j=(i-1)*blo+1;j<=min(i*blo,n);++j)
    			change(a[j],-1);
    	}
    	read(m);
    	int now=0;
    	while(m--)
    	{
    		int opt;
    		read(opt);
    		if(opt==0)
    		{
    			int L,R;
    			read(L);read(R);
    			L^=now,R^=now;
    			now=0;
    			int l=bl[L],r=bl[R];
    			if(r-l<=1) // in no more than 2 blocks
    			{
    				for(int i=L;i<=R;++i)
    				{
    					now+=query(n)-query(a[i]);
    					change(a[i],1);
    				}
    				for(int i=L;i<=R;++i)
    					change(a[i],-1);
    			}
    			else
    			{
    				for(int i=l+1;i<r;++i) // middle
    				{
    					now+=num[i];
    					now+=query2(i,r-1)-query2(i,i);
    				}
    				for(int i=L;i<=l*blo;++i) // left
    				{
    					now+=query(n)-query(a[i]);
    					now+=query3(r-1,a[i]-1)-query3(l,a[i]-1);
    					change(a[i],1);
    				}
    				for(int i=(r-1)*blo+1;i<=R;++i) // right
    				{
    					now+=query(n)-query(a[i]);
    					now+=query3(r-1,n)-query3(l,n)-query3(r-1,a[i])+query3(l,a[i]);
    					change(a[i],1);
    				}
    				for(int i=L;i<=l*blo;++i) 
    					change(a[i],-1);
    				for(int i=(r-1)*blo+1;i<=R;++i)
    					change(a[i],-1);	
    			}
    			printf("%d
    ",now);
    		}
    		else if(opt==1)
    		{
    			int p,v;
    			read(p);read(v);
    			p^=now,v^=now;
    			for(int i=bl[p]+1;i<=bl[n];++i) // modify right ans
    			{
    				int t=query3(i,v-1)-query3(i-1,v-1); // add new
    				t-=query3(i,a[p]-1)-query3(i-1,a[p]-1); // del old
    				change2(bl[p],i,t);
    			}
    			for(int i=1;i<bl[p];++i) // modify left ans
    			{
    				int t=query3(i,n)-query3(i-1,n)-query3(i,v)+query3(i-1,v); // add new
    				t-=query3(i,n)-query3(i-1,n)-query3(i,a[p])+query3(i-1,a[p]); // del old
    				change2(i,bl[p],t);
    			}
    			for(int i=bl[p];i<=bl[n];++i) //modify suffix sum
    			{
    				change3(i,a[p],-1);
    				change3(i,v,1);
    			}
    			a[p]=v;
    			num[bl[p]]=0;
    			for(int i=(bl[p]-1)*blo+1;i<=min(bl[p]*blo,n);++i) // cal num
    			{
    				num[bl[p]]+=query(n)-query(a[i]);
    				change(a[i],1);
    			}
    			for(int i=(bl[p]-1)*blo+1;i<=min(bl[p]*blo,n);++i)
    				change(a[i],-1);
    		}
    	}
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    
    
    
  • 相关阅读:
    yii2美化url
    Android 百度地图API 定位 导航
    辛星浅谈PHP的混乱的编码风格
    html5非常火,他究竟与html4有何差别?
    Cocos2d-x 3.0心得(01)-图片载入与混合模式
    解读BOM与COM
    HDU 1718 Rank counting sort解法
    汉语转拼音pinyin4j
    UVALive-6656-Watching the Kangaroo(二分)
    thinPHP中多维数组的遍历
  • 原文地址:https://www.cnblogs.com/autoint/p/9544596.html
Copyright © 2011-2022 走看看