トピックポータル
https://lydsy.com/JudgeOnline/problem.php?id=5016
問題の解決策
元の式は、そのようなものである
\ [\ sum_ {X = 0
} ^ {\ inftyのは} \ CDOT(L_2、R_2、X)\得る(X、L_1、R_1)を取得]をので、2つの問い合わせ間隔を使用する必要性は、希望間違いなく2つのツリー会長のクエリ間隔で最高構築する方法はありません。
次に、ブロックやMoチームは、その後、何もしません。
主な問い合わせが2つのパラメータのみを必要とするように、だから我々は、クエリ自体にいくつかの変更を検討してください。
\ [\ sum_ {X = 0} ^ {\ inftyの}得る(L_1、R_1、X)\ CDOT得る(L_2、R_2、X)\\ = \ sum_ {X = 0} ^ {\ inftyの取得}(1 、R_1、X)\ CDOT得る(1、R_2、X) - を取得(1、L1 - 1、X)\ CDOT GET(1、R 2、X) - (1、L2を取得 - 1、X)\ CDOT GET (1、R1、X)+を取得(1、L1 - 1、X)\ CDOT得る(1、L 2 - 1、X)\]
したがって、我々は、聞かせて\(G(b)は \) を表し\(\和の\ limits_ {X = 0} ^ {\ inftyの}(1、x)は\ CDOT(1、B、X)\ゲットを)、その後、我々は上記に分解頼むよ\(4 \)番目の問い合わせを。
その後、\(G(a、b)は \) することができます(A、B \)を\は、 Moの完全なチームでした。
時間複雑\(O(N \ 4M SQRT {})\) 。複雑さは、任意の一定であってはならないので、非常に標準は思えない複雑さを書きました。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 50000 + 7;
#define bl(x) (((x) - 1) / blo + 1)
int n, m, blo, Q;
ll val;
int a[N], cl[N], cr[N];
ll ans[N];
struct Query {
int opt, l, r;
ll *ans;
inline Query() {}
inline Query(const int &opt, const int &l, const int &r, ll *ans) : opt(opt), l(l), r(r), ans(ans) {
if (l > r) std::swap(this->l, this->r);
}
inline bool operator < (const Query &b) const { return bl(l) != bl(b.l) ? l < b.l : r < b.r; }
} q[N << 2];
inline void addl(int x) {
val += cr[a[x]];
++cl[a[x]];
}
inline void addr(int x) {
val += cl[a[x]];
++cr[a[x]];
}
inline void dell(int x) {
val -= cr[a[x]];
--cl[a[x]];
}
inline void delr(int x) {
val -= cl[a[x]];
--cr[a[x]];
}
inline void work() {
blo = sqrt(Q);
std::sort(q + 1, q + Q + 1);
int l = 0, r = 0;
for (int i = 1; i <= Q; ++i) {
while (r < q[i].r) addr(++r);
while (l < q[i].l) addl(++l);
while (l > q[i].l) dell(l--);
while (r > q[i].r) delr(r--);
*q[i].ans += q[i].opt * val;
}
for (int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
}
inline void init() {
read(n);
for (int i = 1; i <= n; ++i) read(a[i]);
read(m);
for (int i = 1; i <= m; ++i) {
int l1, r1, l2, r2;
read(l1), read(r1), read(l2), read(r2);
q[++Q] = Query(1, r1, r2, ans + i);
if (l2 > 1) q[++Q] = Query(-1, l2 - 1, r1, ans + i);
if (l1 > 1) q[++Q] = Query(-1, l1 - 1, r2, ans + i);
if (l1 > 1 && l2 > 1) q[++Q] = Query(1, l1 - 1, l2 - 1, ans + i);
}
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}