您的位置:首页 > 其它

[树套树模板]

2016-04-27 16:51 155 查看
[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
*/


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: