zoukankan      html  css  js  c++  java
  • LOJ#2254. 「SNOI2017」一个简单的询问 莫队

    求 $,sum_{x=0}^{infty} get(l,r,x)get(l_{2},r_{2},x),q$ 组询问.

    由于这里的 $get$ 会涉及到两个区间,所以十分不好处理.

    那么我们就要想办法把这个式子转化成只和一个区间有关的东西.

    考虑拆成前缀和,即 $(s[r]-s[l-1]) imes (s[r_{2}]-s[l_{2}-1])$

    $Rightarrow s[r]s[r_{2}]-s[r]s[l_2-1]-s[l-1]s[r_2]+s[l-1]s[l_2-1]$

    然后我们把这 4 个值看成是新的 4 个区间,用莫队解一下就行了.    

    code: 

    #include <bits/stdc++.h>     
    #define N 50009   
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    int a[N],n,B,m;    
    ll tot,sum[2][N],Ans[N];                 
    struct que
    {   
    	int l,r,id,op;   
    	que(int l=0,int r=0,int id=0,int op=0):l(l),r(r),id(id),op(op){}   
    	bool operator<(const que b) const 
    	{   
    		return (l/B)==(b.l/B)?r<b.r:(l/B)<(b.l/B);     
    	}   
    }q[N<<2];      
    void add(int x,int o) 
    {                     
    	tot-=sum[o][x]*sum[o^1][x];      
    	++sum[o][x];   
    	tot+=sum[o][x]*sum[o^1][x];  
    } 
    void del(int x,int o) 
    {    
    	tot-=sum[o][x]*sum[o^1][x];   
    	--sum[o][x];   
    	tot+=sum[o][x]*sum[o^1][x];   
    }
    int main() 
    { 
    	// setIO("input");       
    	int l=1,r=1,cnt=0,x,y,z;  
    	scanf("%d",&n),B=sqrt(n);         
    	for(int i=1;i<=n;++i) scanf("%d",&a[i]);        
    	scanf("%d",&m);   
    	for(int i=1;i<=m;++i) 
    	{
    		int l1,r1,l2,r2;  
    		scanf("%d%d%d%d",&l1,&r1,&l2,&r2);   
    		q[++cnt]=que(min(r1,r2),max(r1,r2),i,1);  
    		if(l2>1) q[++cnt]=que(min(l2-1,r1),max(l2-1,r1),i,-1);   
    		if(l1>1) q[++cnt]=que(min(l1-1,r2),max(l1-1,r2),i,-1);   
    		if(l1>1&&l2>1) q[++cnt]=que(min(l1-1,l2-1),max(l1-1,l2-1),i,1);   
    	}
    	sort(q+1,q+1+cnt);   
    	sum[0][a[1]]=sum[1][a[1]]=1,tot=1;             
    	for(int i=1;i<=cnt;++i) 
    	{      
    		while(r<q[i].r) add(a[++r],0);   
    		while(l<q[i].l) add(a[++l],1);   
    		while(l>q[i].l) del(a[l--],1);   
    		while(r>q[i].r) del(a[r--],0);              
    		Ans[q[i].id]+=q[i].op*tot;   
    	}        
    	for(int i=1;i<=m;++i)  printf("%lld
    ",Ans[i]);  
    	return 0; 
    }
    

      

  • 相关阅读:
    深入单机事务
    事务的本质
    云计算是什么?
    linux命令之tail
    linux命令之rpm
    String、StringBuffer与StringBuilder区别
    自定义今天的520
    logback中MDC使用
    数组(转载)
    spring获取webapplicationcontext,applicationcontext几种方法详解(转载)
  • 原文地址:https://www.cnblogs.com/guangheli/p/13073688.html
Copyright © 2011-2022 走看看