Strange Queries(莫队)

题目

You are given an array with n integers a1, a2, ..., an, and q queries to answer.

Each query consists of four integers l1, r1, l2 and r2. Your task is to count the number of pairs of indices (i, j) satisfying the following conditions:

ai = aj
l1 ≤ i ≤ r1
l2 ≤ j ≤ r2
Input
The first line of the input contains an integer n (1 ≤ n ≤ 50 000) — the size of the given array.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ n).

The third line contains an integer q (1 ≤ q ≤ 50 000) — the number of queries.

Each of the next q lines contains four integers l1, r1, l2, r2 (1 ≤ l1 ≤ r1 ≤ n, 1 ≤ l2 ≤ r2 ≤ n), describing one query.

Output
For each query count the number of sought pairs of indices (i, j) and print it in a separate line.

Examples
Input
7
1 5 2 1 7 2 2
8
1 3 4 5
2 3 5 7
1 4 3 7
2 6 4 7
1 6 2 5
3 3 6 7
4 5 1 4
2 3 4 5
Output
1
2
5
6
6
2
2
0

题目:

您将获得一个包含n个整数a1,a2,...,an和q查询的数组。

每个查询由四个整数l1,r1,l2和r2组成。您的任务是计算满足以下条件的索引对(i,j)的数量:

$ a_i = a_j $
L1 ≤ i ≤ R1
L2 ≤ j ≤ R2

输入

输入的第一行包含一个整数n(1≤N≤50 000) -给定阵列的大小。

第二行包含n个整数a1,a2,...,a(1≤ai≤n)。

第三行包含一个整数q(1≤q≤50000) - 查询数。

接下来的q行中的每一行包含四个整数l1,r1,l2,r2(1≤l1≤r1≤n,1≤l2≤r2≤n),描述一个查询。

输出

对于每个查询计数所寻求的索引对(i,j)的数量,并将其打印在单独的行中。

示例输入

7 
1 5 2 1 7 2 2 
8 
1 3 4 5 
2 3 5 7 
1 4 3 7 
2 6 4 7 
1 6 2 5 
3 3 6 7 
4 5 1 4 
2 3 4 5 

示例输出

1 
2 
5 
6 
6 
2 
2 
0

仔细观察题目我们不难发现这题我们需要维护两个区间内元素的出现次数

嗯?这不是裸裸的莫队吗?等等,两个(50000)的区间,我不敲时谁敲时?

这谁做得出啊??干脆维护一个区间算了,暴力枚举第二个区间算了!!

于是某年某月某日某蒟蒻以2000毫秒的好成绩卡了过去:

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

struct su{
    int l,r,ll,rr,t;
}k[50001];

long long now;
int z[50001];
int s[50001];
int tot[50001];
int tot2[50001];
long long ans[50001];
int n,m,q,f,l=1,r,ll=1,rr;

inline int qr(){
    char ch;
    while((ch=getchar())<'0'||ch>'9');
    int res=ch^48;
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+(ch^48);
    return res;
}

inline bool cmp(su x,su y){
    return z[x.l]==z[y.l]?x.r<y.r:x.l<y.l;
}

inline void add(int x,int y){
    now-=(long long)tot2[x]*tot[x];
    tot[x]+=y;
    now+=(long long)tot2[x]*tot[x];
}

inline void add2(int x,int y){
    now-=(long long)tot[x]*tot2[x];
    tot2[x]+=y;
    now+=(long long)tot[x]*tot2[x];
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=qr();
    f=sqrt(n-1)+1;
    for(rg i=1;i<=n;++i) s[i]=qr();
    for(rg i=1,j=1;i<=n;++i)
        z[i]=i%f==0?j++:j;
    m=qr();
    for(rg i=1;i<=m;++i){
		k[i].l=qr();
		k[i].r=qr();
		k[i].ll=qr();
		k[i].rr=qr();
		k[i].t=i;
	}
    sort(k+1,k+m+1,cmp);
    for(rg i=1;i<=m;++i){
        while(l<k[i].l)add(s[l],-1),++l;
        while(k[i].l<l)add(s[l-1],1),--l;
        while(r<k[i].r)add(s[r+1],1),++r;
        while(k[i].r<r)add(s[r],-1),--r;
        while(ll<k[i].ll)add2(s[ll],-1),++ll;
        while(k[i].ll<ll)add2(s[ll-1],1),--ll;
        while(rr<k[i].rr)add2(s[rr+1],1),++rr;
        while(k[i].rr<rr)add2(s[rr],-1),--rr;
        ans[k[i].t]=now;
    }
    for(rg i=1;i<=m;++i)
        printf("%lld
",ans[i]);
    return 0;
}
✐☎博主撰文不易,转载还请注明出处;若对本文有疑,请私信或在下方讨论中提出。O(∩_∩)O谢谢!☏

☃〔尽管小伙伴们肯定有千百种方式针对,但博主还是极其非常十分不要脸的把反对键吃掉辣!〕☃

✿『$At$ $last$:非常一(hu)本(shuo)正(ba)经(dao)的:博主很笨,请不要欺负他』✿✍

原文地址:https://www.cnblogs.com/812-xiao-wen/p/10122893.html