zoukankan      html  css  js  c++  java
  • 【BZOJ5016】[Snoi2017]一个简单的询问 莫队

    【BZOJ5016】[Snoi2017]一个简单的询问

    Description

    给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出
    get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次。

    Input

    第一行,一个数字N,表示序列长度。
    第二行,N个数字,表示a1~aN
    第三行,一个数字Q,表示询问个数。
    第4~Q+3行,每行四个数字l1,r1,l2,r2,表示询问。
    N,Q≤50000
    N1≤ai≤N
    1≤l1≤r1≤N
    1≤l2≤r2≤N
    注意:答案有可能超过int的最大值

    Output

    对于每组询问,输出一行一个数字,表示答案

    Sample Input

    5
    1 1 1 1 1
    2
    1 2 3 4
    1 1 4 4

    Sample Output

    4
    1

    题解:先将询问的l--,然后我们开始推式子喽!为了方便起见,下面用s(i)表示get(1,i,x)。那么:

    $ans=sumlimits_{x}(s(r1)-s(l1))*(s(r2)-s(l2)))\=sumlimits_{x}s(r1)*s(r2)+s(l1)*s(l2)-s(l1)*s(r2)-s(r1)*s(l2)\*ab={(a+b)^2-a^2-b^2over 2}*\=sumlimits_{x}{(s(r1)^2+s(r2)^2-(s(r2)-s(r1)))^2+s(l1)^2+s(l2)^2-(s(l2)-s(l1))^2+(s(r2)-s(l1))^2-s(r2)^2-s(l1)^2+(s(r1)-s(l2))^2-s(r1)^2-s(l2)^2over 2}\=sumlimits_{x}{(s(r1)-s(l2))^2+(s(r2)-s(l1))^2-(s(l2)-s(l1))^2-(s(r2)-s(r1))^2over 2}$

    然后用莫队处理区间中每个数出现次数的平方即可!

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=50010;
    struct node
    {
    	int a,b,org,k;
    	node() {}
    	node(int x,int y,int c,int d){a=min(x,y)+1,b=max(x,y),org=c,k=d;}	
    }q[maxn<<2];
    int s[maxn],v[maxn];
    int n,m,B;
    ll sum,ans[maxn];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    bool cmp(node a,node b)
    {
    	return (a.a/B==b.a/B)?(a.b<b.b):(a.a/B<b.a/B);
    }
    int main()
    {
    	n=rd(),B=int(sqrt(double(n)));
    	int i,a,b,c,d,l,r;
    	for(i=1;i<=n;i++)	v[i]=rd();
    	m=rd();
    	for(i=1;i<=m;i++)	a=rd()-1,b=rd(),c=rd()-1,d=rd(),
    		q[i]=node(a,c,i,-1),q[i+m]=node(b,d,i,-1),q[i+2*m]=node(a,d,i,1),q[i+3*m]=node(b,c,i,1);
    	sort(q+1,q+4*m+1,cmp);
    	for(l=1,r=0,i=1;i<=4*m;i++)
    	{
    		while(l>q[i].a)	l--,s[v[l]]++,sum+=2*s[v[l]]-1;
    		while(l<q[i].a)	sum-=2*s[v[l]]-1,s[v[l]]--,l++;
    		while(r<q[i].b)	r++,s[v[r]]++,sum+=2*s[v[r]]-1;
    		while(r>q[i].b)	sum-=2*s[v[r]]-1,s[v[r]]--,r--;
    		ans[q[i].org]+=q[i].k*sum;
    	}
    	for(i=1;i<=m;i++)	printf("%lld
    ",ans[i]>>1);
    	return 0;
    }

     

  • 相关阅读:
    总结第一、二类斯特林数(模板)
    总结组合数的几种求法(模板)
    HDU5521 Meeting(dijkstra+巧妙建图)
    BZOJ4152 The Captain(dijkstra+巧妙建图)
    CF1194D 1-2-K Game (博弈论)
    JavaScript字符串的操作
    JavaScript基础–闭包
    JavsScript基础–声明提升
    JavaScript基础–作用域
    css基础(一)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7500549.html
Copyright © 2011-2022 走看看