「SNOI2017」シンプル問い合わせ

「SNOI2017」シンプル問い合わせ

簡単な解決策

もちろん、あなたは違いを見ることができます。
\ [プレゼント(L、R、 X)\回得る(L1、R1、X)= GET(1、R、X)\回取得し(1、R1、X)-get(1、L、X) \時刻を取得(1、R1、 X)-get(1、R、X)\回取得し(1、L1-1、X)+得る(1、L-1、X)\回取得し(1、L1- 1は、X)\]
彼らが1を開始したので、次に、二つの配列を覚えプレフィックスを表し、そして次に四つの部分、MOチームに分けることができるCNT。

#include <bits/stdc++.h>
#define rep(q, a, b) for (int q = a, q##_end_ = b; q <= q##_end_; ++q)
#define dep(q, a, b) for (int q = a, q##_end_ = b; q >= q##_end_; --q)
#define mem(a, b) memset(a, b, sizeof a)
#define debug(a) cerr << #a << ' ' << a << "___" << endl
using namespace std;
bool cur1;
char buf[10000000], *p1 = buf, *p2 = buf;
#define Getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin), p1 == p2) ? EOF : *p1++
void in(int &r) {
    static char c;
    r = 0;
    while (c = Getchar(), c < 48)
        ;
    do
        r = (r << 1) + (r << 3) + (c ^ 48);
    while (c = Getchar(), c > 47);
}
const int mn = 50005;
int K, n, val[mn];
long long ans[mn];
struct node {
    int l, r, id, ty;
    bool operator<(const node &A) const {
        return l / K == A.l / K ? (l / K & 1 ? r > A.r : r < A.r) : l / K < A.l / K;
    }
} an[mn * 4];
int cnt[mn], cnt1[mn];
long long mid_ans;
bool cur2;
int main() {
    //  cerr<<(&cur2-&cur1)/1024.0/1024<<endl;
    in(n);
    K = sqrt(n) + 1;
    rep(q, 1, n) in(val[q]);
    int Q;
    in(Q);
    int l, r, l1, r1;
    int ct = 0;
    rep(q, 1, Q) {
        in(l), in(r), in(l1), in(r1);
        an[++ct] = { r, r1, q, 1 };
        if (l > 1) {
            an[++ct] = { l - 1, r1, q, -1 };
            if (l1 > 1)
                an[++ct] = { l1 - 1, l - 1, q, 1 };
        }
        if (l1 > 1)
            an[++ct] = { l1 - 1, r, q, -1 };
    }
    sort(an + 1, an + ct + 1);
    l = 0, r = 0;
    rep(q, 1, ct) {
        while (l > an[q].l) mid_ans -= cnt1[val[l]], --cnt[val[l--]];
        while (r < an[q].r) mid_ans += cnt[val[++r]], ++cnt1[val[r]];
        while (l < an[q].l) mid_ans += cnt1[val[++l]], ++cnt[val[l]];
        while (r > an[q].r) mid_ans -= cnt[val[r]], --cnt1[val[r--]];
        ans[an[q].id] += mid_ans * an[q].ty;
    }
    rep(q, 1, Q) printf("%lld\n", ans[q]);
    return 0;
}

トラブルの解決

二つのセクションのための\([L、R&LT]、[L1、R1](L \ L1 1当量)\) 三種類の包含および除外。

  1. 払ってはいけません
  2. \([L1、R1] \ ) される([L、R] \ \ ) を含みます
  3. 2つの間隔を交差し、何の関係が含まれていません

1の場合

\([L、R] \ ) 数K Xとの値、\([R&LT +。1、L1-1] \)数K Yとの値、\([L1、R1] \)の数Kとの値をZ。
\ [XZ = {(X +
Y + Z)^ 2-(X + Y)^ 2-(Y + Z)^ 2 + y ^ 2 \ 2オーバー} \]は4つのセクションに分割することができるが算出されます。

2の場合

\([L、L1-1] \ ) 数K Xとの値、\([L1、R1] \)の値数K Yと、\([R1 +。1、R&LT] \)の数Kとの値をZ。
\ [Y(X + Y +
Z)= {(X + Y)^ 2 +(Y + Z)2上^ 2-X ^ 2-z ^ 2 \} \]は4つのセクションに分割することができるが算出されます。

3の場合

\([L、L1-1] \ ) 数K Xと値\([L1、R&LT] \)数K Y、との値\([R&LT +。1、R1] \)の数Kとの値をZ。
\ [(X + Y)(
Y + Z)= {(X + Y + Z)^ 2-X ^ 2-z ^ 2 + y ^ 2 \ 2オーバー} \] 4つのセクションに分割することができるが算出されます。

要約で

同じ数と間隔の数の二乗を計算するために、再びチームを、それを実行してください。

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
bool cur1;
char buf[10000000],*p1=buf,*p2=buf;
#define Getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++
void in(int &r) {
    static char c;
    r=0;
    while(c=Getchar(),c<48);
    do r=(r<<1)+(r<<3)+(c^48);
    while(c=Getchar(),c>47);
}
const int mn=50005;
int K,n,val[mn];
long long ans[mn];
struct node{
    int l,r,id,ty;
    bool operator <(const node &A)const{
        return l/K==A.l/K?(l/K&1?r>A.r:r<A.r):l/K<A.l/K;
    }
}an[mn*4];
int cnt[mn];
long long mid_ans;
bool cur2;
int main(){
//  cerr<<(&cur2-&cur1)/1024.0/1024<<endl;
    in(n);
    K=sqrt(n)+1;
    rep(q,1,n)in(val[q]);
    int Q;
    in(Q);
    int l,r,l1,r1;
    int ct=0;
    rep(q,1,Q){
        in(l),in(r),in(l1),in(r1);
        if(l>l1)swap(l,l1),swap(r,r1);
        if(r<l1){
            an[++ct]={l,r1,q,1};
            an[++ct]={l,l1-1,q,-1};
            an[++ct]={r+1,r1,q,-1};
            if(l1-1>=r+1)an[++ct]={r+1,l1-1,q,1};
        }else if(r1<=r){
            an[++ct]={l,r1,q,1};
            an[++ct]={l1,r,q,1};
            if(l<=l1-1)an[++ct]={l,l1-1,q,-1};
            if(r1+1<=r)an[++ct]={r1+1,r,q,-1};
        }else{
            an[++ct]={l,r1,q,1};
            an[++ct]={l1,r,q,1};
            if(l<=l1-1)an[++ct]={l,l1-1,q,-1};
            if(r+1<=r1)an[++ct]={r+1,r1,q,-1};
        }
    }
    sort(an+1,an+ct+1);
    mid_ans=1,cnt[val[1]]=1;
    l=1,r=1;
    rep(q,1,ct){
        while(l>an[q].l)--l,mid_ans+=(cnt[val[l]]++)<<1|1;
        while(r<an[q].r)++r,mid_ans+=(cnt[val[r]]++)<<1|1;
        while(l<an[q].l)mid_ans-=(--cnt[val[l]])<<1|1,++l;
        while(r>an[q].r)mid_ans-=(--cnt[val[r]])<<1|1,--r;
        ans[an[q].id]+=mid_ans*an[q].ty;
    }
    rep(q,1,Q)printf("%lld\n",ans[q]>>1);
    return 0;
}

おすすめ

転載: www.cnblogs.com/klauralee/p/10948943.html