[루오 구 P5286] 간단한 문의

문제 설명

당신에게 길이를 부여하려면 \ (N \) 순서 \ (A_I \) , \ (. 1 \ LEQ I \ LEQ N은 \)\ (Q \) 그룹 쿼리, 각 쿼리 읽기 \ (l_1, R_1, L_2는 R_2는 \) , 출력 될

\ (\ 합계 \ limits_ {X = 0} ^ \ infty \ 텍스트 GET {} (l_1, R_1, X) \ 시간 \ 텍스트 GET {} (l_2, R_2, X) \) .

\ (\ 텍스트 GET {}는 ( L은, R, X)이 \) 계산 부를 나타내고 \ ([L, R] \ ) , 디지털 \ (X는 \) 여러 번 나타난다.

입력 형식

첫번째 라인 디지털 \ (N은 \) , 시퀀스 길이를 나타낸다.
두 번째 라인 \ (N \) 숫자가 나타내는 \ (A_1 \ SIM a_N \) .
셋째 행 번호 \ (Q는 \) , 질의의 수를 나타낸다.
\ (4 \ SIM Q + 3 \) 네 자리의 행 (\ L_1, R_1, L_2, R_2 \) 문의를 나타낸다.

출력 형식

각 조회, 출력 라인 답을 나타내는 숫자의 경우.

샘플 입력

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

샘플 출력

4
1

설명

\ (20 \ % \) 데이터 \ (1 \ 당량 N, Q \ 당량 1,000 \.) ,
추가로 대 \ (30 \ % \) 데이터 \ (1 \ 당량 A_I \ 당량 50 \.) ]
에 대한 (\ 100 \ % \) 데이터 \ (N, Q \ 당량 50000 \) \ (. 1 \ 당량 A_I \ 당량 N \) \ (. 1 \ 당량 L_1 \ 당량 R_1 \ 당량 N \) \ ( . 1 \ 당량 L_2 \ 당량 R_2 \ 당량 N \) .

동일한 데이터가 원래의 제목으로 다양하지만, 테스트 데이터는 LibreOJ 아닌 원래의 데이터로 만들었다.

주 : 대답은 초과 할 가능성이 int최대 값을.

해결

간격 문제는 종종 접두사 생각합니다. 이 수식은 프리픽스 및 형태를 나타내고 사용하기 위해서는 다음과 같은 절차에 따라 단순화 될 수있다 :
\ [\를 \ sum_ I = {0} ^ {\ infty} GET (L_1, R_1, X) \ GET 시간}를이 {시작 정렬 (l_2는 R_2는, X는) = & \ sum_ {I = 0} ^ {\ infty} GET (0 R_1, X) \ 번하세요 (0, R_2, X \\) - & \ sum_ {I = 0} ^ {\ infty} GET (0 , l_1-1, x)는 시간 얻을 \ (0, R_2, X \\) - & \ sum_ {I = 0} ^ {\ infty} GET (0 R_1, X) \ 번하세요 (0 l_2-1, X ) + \\ 및 \ sum_ {I = 0} ^ {\ infty} GET (0 l_1-1, x)는 시간 얻을 \ (0 l_2-1, X) \ 끝 {정렬}는 \]
이 방법으로, 우리는 모 문의를 유지하기 위해 4 개 팀으로 쿼리가 분할 될 수 있습니다 넣어. 각 문의 메인터넌스 \ (NUM은 [0] [X ] \)은 간격 나타내는 \ ([1,1] \ ) 에서 \ (X \) 가되어 많은 시간을 가지고, \ (NUM [1] [X 방향]을 \ ) 의 간격을 나타내는 \ ([1, R] \가 ) 에서 \ (X는 \)가 존재하고있는 여러 번. 대답은 \ (\ SUM \ limits_ {X = 0} ^ \ infty NUM [0] [X] NUM *. 1] [X] \) . 수정 작업함에 따라, 볼 : 수많은 가정이 밝혀졌다 \ (A * B를 \)이제 안으로 들어가 \ ((A + 1) B * \) , 사실, 원래 기초 동등 \ (b \) . 여기에 같은 이유입니다.

코드

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define int long long
#define N 50002
using namespace std;
struct query{
    int l,r,id;
}q[4*N];
int n,m,i,a[N],b[N],gap,cnt,num[2][N],sum,ans[4*N],l,r;
int read()
{
    char c=getchar();
    int w=0;
    while(c<'0'||c>'9') c=getchar();
    while(c<='9'&&c>='0'){
        w=w*10+c-'0';
        c=getchar();
    }
    return w;
}
int my_comp(const query &x,const query &y)
{
    if(b[x.l]==b[y.l]) return x.r<y.r;
    return x.l<y.l;
}
void add(int op,int x)
{
    num[op][a[x]]++;
    sum+=num[op^1][a[x]];
}
void del(int op,int x)
{
    num[op][a[x]]--;
    sum-=num[op^1][a[x]];
}
signed main()
{
    n=read();
    gap=sqrt(1.0*n);
    for(i=1;i<=n;i++) a[i]=read();
    for(i=1;i<=n;i++) b[i]=(i-1)/gap+1;
    m=read();
    for(i=1;i<=m;i++){
        int l1=read(),r1=read(),l2=read(),r2=read();
        q[++cnt]=(query){min(r1,r2),max(r1,r2),cnt};
        q[++cnt]=(query){min(r1,l2-1),max(r1,l2-1),cnt};
        q[++cnt]=(query){min(l1-1,r2),max(l1-1,r2),cnt};
        q[++cnt]=(query){min(l1-1,l2-1),max(l1-1,l2-1),cnt};
    }
    sort(q+1,q+cnt+1,my_comp);
    for(i=1;i<=cnt;i++){
        while(l<q[i].l) add(0,++l);
        while(l>q[i].l) del(0,l--);
        while(r<q[i].r) add(1,++r);
        while(r>q[i].r) del(1,r--);
        ans[q[i].id]=sum;
    }
    for(i=1;i<=cnt;i+=4) printf("%lld\n",ans[i]-ans[i+1]-ans[i+2]+ans[i+3]);
    return 0;
}

추천

출처www.cnblogs.com/LSlzf/p/12194881.html