第一問就是主席樹了。
依據套路, 對於每個數 x, 記錄上一次出現的位置 prex, 於是問題就變成了: 查詢區間 [l,r] 內, 值域 [a,b] 內, pre [0,l-1] 內的數, 是個三維的偏序問題。
看上去一般做法要 O(log3), 但沒有修改, 可以可持久化降一維。
然後剩下的二維問題就樹套樹解決了。
當然,開玩笑的, 第一維離線降下來就行了。
#include<bits/stdc++.h>
#define INF 2147483647
using namespace std;
const int N = 1e5 + 3, SZ = N*20*2+233;
int n, m, a[N], las[N], pre[N];
struct ques {
int l, r, a, b;
int ans1, ans2;
} obj[N];
int ecnt, hd[N], nt[N*2+3], vr[N*2+3];
void ad(int u, int v) { nt[++ecnt] = hd[u], hd[u] = ecnt; vr[ecnt] = v; }
namespace BIT {
int t[N];
void ins(int x) {
for(; x<=n; x+=(x&(-x))) ++t[x];
}
int ask_(int x) {
int res = 0;
for(; x; x-=x&(-x)) res += t[x];
return res;
}
int ask(int l, int r) { return ask_(r) - ask_(l-1); }
}
int cnt;
#define newnode(s, v, a, b) (&(*pool[cnt++] = node(s, v, a, b)))
#define merge(a, b) newnode(a->siz+b->siz, b->val, a, b)
#define upd(me) if(me->ls->siz) me->siz=me->ls->siz+me->rs->siz, me->val=me->rs->val
struct node {
int siz, val;
node *ls, *rs;
node(int s, int v, node *a, node *b) : siz(s), val(v), ls(a), rs(b) {
}
node() {
}
} *root[N], *emp, t[SZ], *pool[SZ];
inline void maintain(node *me) {
if(me->ls->siz > me->rs->siz * 4)
me->rs = merge(me->ls->rs, me->rs), pool[--cnt] = me->ls, me->ls = me->ls->ls;
if(me->rs->siz > me->ls->siz * 4)
me->ls = merge(me->ls, me->rs->ls), pool[--cnt] = me->rs, me->rs = me->rs->rs;
}
void ins(int x, node *me) {
if(me->siz == 1)
me->ls = newnode(1, min(x, me->val), emp, emp),
me->rs = newnode(1, max(x, me->val), emp, emp);
else
ins(x, x>me->ls->val ? me->rs : me->ls), maintain(me);
upd(me);
}
int low(int x, node *me) {
if(me->siz == 1) return (me->val <= x);
else return x>=me->ls->val ? me->ls->siz + low(x, me->rs) : low(x, me->ls);
}
namespace nbBIT {
void ins(int x, int v) {
for(; x<=n; x+=(x&(-x))) ins(v, root[x]);
}
int ask_(int x, int v) {
int res = 0;
for(; x; x-=(x&(-x))) res += low(v, root[x]);
return res;
}
int ask(int l, int r, int v) {
return ask_(r, v) - ask_(l-1, v);
}
}
int main() {
emp = new node(0, 0, NULL, NULL);
for(int i=0; i<SZ; ++i) pool[i] = &t[i];
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i) root[i] = newnode(1, INF, emp, emp);
for(int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
pre[i] = las[a[i]];
las[a[i]] = i;
}
// May I have your Name ?
for(int i=1; i<=m; ++i) {
scanf("%d%d%d%d", &obj[i].l, &obj[i].r, &obj[i].a, &obj[i].b);
obj[i].ans1 = obj[i].ans2 = 0;
if(obj[i].l - 1) ad(obj[i].l - 1, i);
ad(obj[i].r, i);
}
// My name is F#
for(int i=1; i<=n; ++i) {
BIT::ins(a[i]);
nbBIT::ins(a[i], pre[i]);
// cout << "# " << pre[i] << '\n';
for(int j = hd[i]; j; j = nt[j]) {
int id = vr[j];
if(i == obj[id].l-1)
{
obj[id].ans1 -= BIT::ask(obj[id].a, obj[id].b);
obj[id].ans2 -= nbBIT::ask(obj[id].a, obj[id].b, obj[id].l - 1);
}
if(i == obj[id].r)
{
obj[id].ans1 += BIT::ask(obj[id].a, obj[id].b);
obj[id].ans2 += nbBIT::ask(obj[id].a, obj[id].b, obj[id].l - 1);
}
}
}
for(int i=1; i<=m; ++i) cout << obj[i].ans1 << ' ' << obj[i].ans2 << '\n';
return 0;
}