loj #2254. 「SNOI2017」一个简单的询问 #2254. 「SNOI2017」一个简单的询问

题目描述

给你一个长度为 NNN 的序列 aia_iai​​,1≤i≤N1leq ileq N1iN,和 qqq 组询问,每组询问读入 l1,r1,l2,r2l_1,r_1,l_2,r_2l1​​,r1​​,l2​​,r2​​,需输出

∑x=0∞get(l1,r1,x)⋅get(l2,r2,x) sumlimits_{x=0}^infty ext{get}(l_1,r_1,x)cdot ext{get}(l_2,r_2,x)x=0​​get(l1​​,r1​​,x)get(l2​​,r2​​,x)

get(l,r,x) ext{get}(l,r,x)get(l,r,x) 表示计算区间 [l,r][l,r][l,r] 中,数字 xxx 出现了多少次。

输入格式

第一行,一个数字 NNN,表示序列长度。
第二行,NNN 个数字,表示 a1∼aNa_1sim a_Na1​​aN​​。
第三行,一个数字 QQQ,表示询问个数。
第 4∼Q+34sim Q+34Q+3 行,每行四个数字 l1,r1,l2,r2l_1,r_1,l_2,r_2l1​​,r1​​,l2​​,r2​​,表示询问。

输出格式

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

样例

样例输入

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

样例输出

4
1

数据范围与提示

对于 20%20\%20% 的数据,1≤N,Q≤10001leq N,Qleq 10001N,Q1000;
对于另外 30%30\%30% 的数据,1≤ai≤501leq a_ileq 501ai​​50;
对于 100%100\%100% 的数据,N,Q≤50000N,Qleq 50000N,Q50000,1≤ai≤N1leq a_ileq N1ai​​N,1≤l1≤r1≤N1leq l_1leq r_1leq N1l1​​r1​​N,1≤l2≤r2≤N1leq l_2leq r_2leq N1l2​​r2​​N。

数据范围与原题相同,但测试数据由本站会员自制,并非原数据。
时限已按照评测机速度调整,原题时限为 2000 ms,省选评测时调整为 4000 ms,这里按 4000 ms 调整。

注意:答案有可能超过 int 的最大值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50010
using namespace std;
int n,a[maxn],b[maxn],l1,r1,l2,r2,mx,cnt[maxn][2],num;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(b+1,b+n+1);
    num=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++)
        a[i]=lower_bound(b+1,b+num+1,a[i])-b;
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        memset(cnt,0,sizeof(cnt));
        for(int i=l1;i<=r1;i++)cnt[a[i]][0]++;
        for(int i=l2;i<=r2;i++)cnt[a[i]][1]++;
        long long ans=0;
        for(int i=1;i<=num;i++)ans+=1LL*cnt[i][0]*cnt[i][1];
        cout<<ans<<endl;
    }
    return 0;
}
80分 暴力
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 50010
using namespace std;
int n,block[maxn],sz,a[maxn],num1[maxn],num2[maxn],m,tot,L,R;
long long res=0,Ans[maxn];
struct node{
    int l,r,id,ad;
    bool operator < (const node &b)const{
        if(block[l]==block[b.l])return r<b.r;
        return l<b.l;
    }
}q[maxn*4];
int main(){
    scanf("%d",&n);sz=sqrt(n);
    for(int i=1;i<=n;i++)block[i]=(i-1)/sz+1;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    scanf("%d",&m);
    int l1,l2,r1,r2;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        q[++tot]=(node){r1,r2,i,1};
        q[++tot]=(node){r1,l2-1,i,-1};
        q[++tot]=(node){l1-1,r2,i,-1};
        q[++tot]=(node){l1-1,l2-1,i,1};
    }
    sort(q+1,q+tot+1);
    for(int i=1;i<=tot;i++){
        while(L<q[i].l)L++,res+=num2[a[L]],++num1[a[L]];
        while(L>q[i].l)res-=num2[a[L]],--num1[a[L]],--L;
        while(R<q[i].r)++R,res+=num1[a[R]],++num2[a[R]];
        while(R>q[i].r)res-=num1[a[R]],--num2[a[R]],--R;
        Ans[q[i].id]+=q[i].ad*res;
    }
    for(int i=1;i<=m;i++)cout<<Ans[i]<<endl;
    return 0;
}
100分 莫队