AHOI2013 作業

第一問就是主席樹了。

依據套路, 對於每個數 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章