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;
    }
    
    
    
  • 相关阅读:
    DVWA 黑客攻防演练(十)反射型 XSS 攻击 Reflected Cross Site Scripting
    DVWA 黑客攻防演练(九) SQL 盲注 SQL Injection (Blind)
    DVWA 黑客攻防演练(八)SQL 注入 SQL Injection
    DVWA 黑客攻防演练(七)Weak Session IDs
    DVWA 黑客攻防演练(六)不安全的验证码 Insecure CAPTCHA
    DVWA 黑客攻防演练(五)文件上传漏洞 File Upload
    工作流表结构设计
    Visual Studio 2019尝鲜----新建空项目体验
    《使用CSLA 2019:CSLA .NET概述》原版和机译文档下载
    .NET快速开发平台的在线预览
  • 原文地址:https://www.cnblogs.com/autoint/p/9544596.html
Copyright © 2011-2022 走看看