zoukankan      html  css  js  c++  java
  • Luogu5268 SNOI2017一个简单的询问

    Description

    link

    给定一个长度为 (n) 的序列,定义函数 (get(l,r,x))(x) 在区间 ([ l,r ]) 的出现次数

    (m) 个询问,每个询问给出四个参数 (l_1,r_1,l_2,r_2),求出

    [sum_{x=0}^{infty} get(l_1,r_1,x) imes get(l_2,r_2,x) ]

    Solution

    首先我们发现 (get(l,r,x)) 这样的函数并不是很好求,而且是乘积

    那么我们差分一下:(get(1,r,x)-get(1,l-1,x))

    把式子一展开,我们的每个询问就变成了四个类似的从 (1) 开始,求区间相关值乘积了

    (把 (get(1,y,x)) 直接写成 (get(y,x)) 了)

    [sum_{x=0} ^{infty} get(l_1-1,x) imes get(l_2-1,x)+get(r_1-1,x) imes get(r_2-1,x)-get(l_1-1,x) imes get(r_2,x)-get(r_1,x) imes get(l_2-1,x) ]

    直接莫队 (+) 贡献统计即可

    其实不太像入门题意义下的莫队,就是在统计答案的时候排序优化复杂度的一个方法

    Code

    #include<bits/stdc++.h>
    using namespace std;
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=50010;
    	int n,T,cnt,a[N],bl[N],block,l,r;
    	struct node{
    		int l,r,fl,id;
    		inline void init(int a,int b,int c,int d){l=a,r=b,fl=c,id=d; return ;}
    		bool operator <(const node s) const
    		{
    			if(bl[l]!=bl[s.l]) return bl[l]<bl[s.l];
    			return r<s.r;
    		}
    	}q[N<<2];
    	int app1[N],app2[N],res,ans[N];
    	inline void del1(int x)
    	{
    		app1[x]--; res-=app2[x];
    		return ;
    	}
    	inline void add1(int x)
    	{
    		app1[x]++; res+=app2[x];
    		return ;
    	}
    	inline void add2(int x)
    	{
    		app2[x]++; res+=app1[x];
    		return ;
    	}
    	inline void del2(int x)
    	{
    		app2[x]--; res-=app1[x];
    		return ;
    	}
    	signed main()
    	{
    		n=read(); block=sqrt(n);
    		for(int i=1;i<=n;++i) bl[i]=(i-1)/block+1,a[i]=read();
    		T=read();
    		for(int i=1,l1,l2,r1,r2;i<=T;++i)
    		{
    			l1=read(),r1=read(),l2=read(),r2=read();
    			q[++cnt].init(l1-1,l2-1,1,i);
    			q[++cnt].init(r1,r2,1,i);
    			q[++cnt].init(l1-1,r2,-1,i);
    			q[++cnt].init(r1,l2-1,-1,i);
    		}
    		for(int i=1;i<=cnt;++i)
    		{
    			if(q[i].l>q[i].r) swap(q[i].l,q[i].r);
    		} sort(q+1,q+cnt+1);
    		for(int i=1;i<=cnt;++i)
    		{
    			while(l<q[i].l) ++l,add1(a[l]);
    			while(l>q[i].l) del1(a[l]),--l;
    			while(r<q[i].r) ++r,add2(a[r]);
    			while(r>q[i].r) del2(a[r]),--r;
    			ans[q[i].id]+=q[i].fl*res;
    		}
    		for(int i=1;i<=T;++i) printf("%d
    ",ans[i]);
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    BZOJ2241 [SDOI2011]打地鼠 【模拟】
    K-D tree入门
    BZOJ1924 [Sdoi2010]所驼门王的宝藏 【建图 + tarjan】
    BZOJ1925 [Sdoi2010]地精部落 【dp】
    BZOJ1926 [Sdoi2010]粟粟的书架 【主席树 + 二分 + 前缀和】
    BZOJ2457 [BeiJing2011]双端队列 【贪心】
    二进制集合枚举子集
    BZOJ1923 [Sdoi2010]外星千足虫 【高斯消元】
    BZOJ1922 [Sdoi2010]大陆争霸 【最短路】
    HDU3157:Crazy Circuits——题解
  • 原文地址:https://www.cnblogs.com/yspm/p/13235122.html
Copyright © 2011-2022 走看看