[树套树模板]

[COGS 2282]黑树白

询问一条链上a<=权值<=b的点有多少个。

用树剖+树套树水了一下。。(Orz stdafx)

然而正解并不是酱紫。。

蛤蛤~

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 100010
using namespace std;

int n, m, a[maxn];
//---------------struct for tree-----------------//
const int Root = 1;
struct Edge{int to, nxt;}edge[maxn << 1];
int h[maxn], cnt;
void add(int u, int v){
	cnt ++;
	edge[cnt].to = v;
	edge[cnt].nxt = h[u];
	h[u] = cnt;
}

int dep[maxn], fa[maxn], top[maxn], s[maxn], son[maxn], pos[maxn];
int dfs_clock;

void dfs1(int u){
	s[u] = 1, dep[u] = dep[fa[u]] + 1;
	for(int i = h[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(v == fa[u])continue;
		fa[v] = u;
		dfs1(v);
		s[u] += s[v];
		if(s[v] > s[son[u]])
		    son[u] = v;
	}
}

void dfs2(int u, int tp){
	top[u] = tp;
	pos[u] = ++ dfs_clock;
	if(son[u])dfs2(son[u], tp);
	for(int i = h[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(v == fa[u] || v == son[u])continue;
		dfs2(v, v);
	}
}
//-----------------------------------------------//
#define M 2000010
int c[M][2], val[M], w[M], size[M], rnd[M], Size;
int root[maxn << 2];

void pushup(int o){
	size[o] = size[c[o][0]] + size[c[o][1]] + w[o];
}

void rotate(int& o, int mark){
	int cur = c[o][mark];
	c[o][mark] = c[cur][mark ^ 1];
	c[cur][mark ^ 1] = o;
	size[cur] = size[o];
	pushup(o); o = cur;
}

int Newnode(int num){
	int cur = ++ Size;
	val[cur] = num;
	rnd[cur] = rand();
	size[cur] = w[cur] = 1;
	c[cur][0] = c[cur][1] = 0;
	return cur;
}

void Insert(int& o, int num){
	if(o == 0){o = Newnode(num);return;}
	size[o] ++;
	if(val[o] == num){w[o] ++;return;}
	if(num < val[o]){
		Insert(c[o][0], num);
		if(rnd[c[o][0]] > rnd[o])
		    rotate(o, 0);
	}
	else{
		Insert(c[o][1], num);
		if(rnd[c[o][1]] > rnd[o])
		    rotate(o, 1);
	}
}

void Delete(int& o, int num){
	if(val[o] == num){
		if(w[o] > 1){
			w[o] --;
			size[o] --;
			return;
		}
		if(c[o][0] == 0 || c[o][1] == 0)
		    o = c[o][0] + c[o][1];
		else if(rnd[c[o][0]] > rnd[c[o][1]])
		    rotate(o, 0), Delete(o, num);
		else rotate(o, 1), Delete(o, num);
		return;
	}
	if(num < val[o])Delete(c[o][0], num);
	else Delete(c[o][1], num);
	size[o] --;
}
#define lc id << 1
#define rc id << 1 | 1
void build(int id, int l, int r, int p, int nw){
	Insert(root[id], nw);
	if(l == r)return;
	int mid = l + r >> 1;
	if(p <= mid)build(lc, l, mid, p, nw);
	else build(rc, mid+1, r, p, nw);
}

void change(int id, int l, int r, int p, int nw, int lt){
	Delete(root[id], lt);
	Insert(root[id], nw);
	if(l == r)return;
	int mid = l + r >> 1;
	if(p <= mid)change(lc, l, mid, p, nw, lt);
	else change(rc, mid+1, r, p, nw, lt);
}

int Find(int o, int nw){
	if(o == 0)return 0;
	if(nw >= val[o])return size[c[o][0]] + w[o] + Find(c[o][1], nw);
	return Find(c[o][0], nw);
}

int Query(int id, int l, int r, int L, int R, int nw){
	if(l == L && r == R)return Find(root[id], nw);
	int mid = l + r >> 1;
	if(R <= mid)return Query(lc, l, mid, L, R, nw);
	if(L > mid)return Query(rc, mid+1, r, L, R, nw);
	return Query(lc, l, mid, L, mid, nw) + Query(rc, mid+1, r, mid+1, R, nw);
}

int ask(int u, int v, int nw){
	int ret = 0;
	while(top[u] != top[v]){
		if(dep[top[u]] < dep[top[v]])swap(u, v);
		ret += Query(1, 1, n, pos[top[u]], pos[u], nw);
		u = fa[top[u]];
	}
	if(dep[u] > dep[v])swap(u, v);
	ret += Query(1, 1, n, pos[u], pos[v], nw);
	return ret;
}

int main(){
	freopen("D_Tree.in", "r", stdin);
	freopen("D_Tree.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++)
	    scanf("%d", &a[i]);
	int u, v;
	for(int i = 1; i < n; i ++){
		scanf("%d%d", &u, &v);
		add(u, v), add(v, u);
	}
	dfs1(Root), dfs2(Root, Root);
	for(int i = 1; i <= n; i ++)
	    build(1, 1, n, pos[i], a[i]);
	int ans = 0; char cmd[2];
	while(m --){
		scanf("%s", cmd);
		if(cmd[0] == 'Q'){
			int a, b;
			scanf("%d%d%d%d", &u, &v, &a, &b);
			u = (u + ans) % n + 1, v = (v + ans) % n + 1;
			printf("%d\n", ans = (ask(u, v, b) - ask(u, v, a-1)));
		}
		else{
			scanf("%d%d", &u, &v);
			u = (u + ans) % n + 1, v = (v + ans) % n + 1;
			change(1, 1, n, pos[u], v, a[u]), a[u] = v;
		}
	}
	return 0;
}

/*
Input
5 5
4 3 3 1 1
2 1
3 2
4 3
5 4
M 2 1
M 4 4
M 1 4
Q 2 4 2 3
Q 4 2 1 5
Output
1
4
*/

  

posted @ 2016-04-27 16:51  _Horizon  阅读(426)  评论(0编辑  收藏  举报