记录编号 |
279056 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[HZOI 2015]疯狂的魔法树 |
最终得分 |
100 |
用户昵称 |
Aglove |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
1.804 s |
提交时间 |
2016-07-08 19:31:23 |
内存使用 |
14.04 MiB |
显示代码纯文本
#define MAXN 200010UL
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i, x, y) for(int i = (x) ; i <= (y) ; ++ i)
#define der(i, x, y) for(int i = (x) ; i >= (y) ; -- i)
#define reg(i, x) for(int i = d[x] ; i != -1 ; i = sg[i].nt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
using namespace std;
int n, m, blo, tot = 1, a, b, ans, val, nw, add[MAXN], pos[MAXN], vis[MAXN], fa[MAXN], c[MAXN];
vector <int> v[MAXN];
char s[10];
struct Graph {
int d[MAXN], t;
Graph() { memset(d, -1, sizeof(d)); }
struct Edge { int hou, nt; } sg[MAXN<<1];
void Add_edge(int x, int y) {
sg[t] = (Edge){y, d[x]}, d[x] = t ++;
return;
}
}G, T;
bool cmp(const int &a, const int &b) {
return c[a]<c[b];
}
void Get_block(int x, int _fa) {
fa[x] = _fa;
if(v[pos[_fa]].size()==blo) {
++ tot, pos[x] = tot;
T.Add_edge(pos[_fa], tot);
v[tot].push_back(x);
} else pos[x] = pos[_fa], v[pos[x]].push_back(x);
for(int i = G.d[x] ; i != -1 ; i = G.sg[i].nt) {
if(G.sg[i].hou==_fa) continue;
Get_block(G.sg[i].hou, x);
}
return;
}
int Get_up(vector <int> &v, int val) {
int L = 0, R = v.size()-1;
if(c[v[0]]>val) return -1;
int ret = -1;
while(L<=R) {
int mid = (L+R)>>1;
if(c[v[mid]]<=val) L = mid+1, ret = mid;
else R = mid-1;
}
return ret;
}
int Get_low(vector <int> &v, int val) {
int L = 0, R = v.size()-1;
if(c[v[R]]<val) return -1;
int ret = -1;
while(L<=R) {
int mid = (L+R)>>1;
if(c[v[mid]]>=val) ret = mid, R = mid-1;
else L = mid+1;
}
return ret;
}
int Judge(int x) {
if(vis[x]) {
if(vis[x]>=a&&vis[x]<=b) return v[x].size();
else return 0;
}
int L = Get_low(v[x], a-add[x]);
int R = Get_up(v[x], b-add[x]);
if(L==-1||R==-1) return 0;
return R-L+1;
}
void Dfs_block(int x) {
ans += Judge(x);
for(int i = T.d[x] ; i != -1 ; i = T.sg[i].nt) Dfs_block(T.sg[i].hou);
return;
}
void Dfs_point(int x) {
if(c[x]+add[pos[x]]>=a&&c[x]+add[pos[x]]<=b) ++ ans;
for(int i = G.d[x] ; i != -1 ; i = G.sg[i].nt) {
int nxt = G.sg[i].hou;
if(nxt==fa[x]) continue;
if(pos[nxt]==pos[x]) Dfs_point(nxt);
else Dfs_block(pos[nxt]);
}
return;
}
void Block_add(int x) {
if(vis[x]) vis[x] += val;
else add[x] += val;
for(int i = T.d[x] ; i != -1 ; i = T.sg[i].nt) Block_add(T.sg[i].hou);
return;
}
void Point_add(int x) {
c[x] += val;
for(int i = G.d[x] ; i != -1 ; i = G.sg[i].nt) {
int nxt = G.sg[i].hou;
if(nxt==fa[x]) continue;
if(pos[nxt]==pos[x]) Point_add(nxt);
else Block_add(pos[nxt]);
}
return;
}
void Block_modify(int x) {
add[x] = 0, vis[x] = val;
for(int i = T.d[x] ; i != -1 ; i = T.sg[i].nt) Block_modify(T.sg[i].hou);
return;
}
void Point_modify(int x) {
c[x] = val-add[pos[x]];
for(int i = G.d[x] ; i != -1 ; i = G.sg[i].nt) {
int nxt = G.sg[i].hou;
if(nxt==fa[x]) continue;
if(pos[nxt]==pos[x]) Point_modify(nxt);
else Block_modify(pos[nxt]);
}
return;
}
void Push_down(int x) {
int siz = v[x].size();
rep(i, 0, siz-1) c[v[x][i]] = vis[x];
vis[x] = 0;
return;
}
int main() {
freopen("H_Tree.in", "r", stdin);
freopen("H_Tree.out", "w", stdout);
int x, y;
scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%d", &c[i]);
rep(i, 2, n) scanf("%d%d", &x, &y), G.Add_edge(x, y), G.Add_edge(y, x);
blo = 250, pos[0] = 1, Get_block(1, 0);
rep(i, 1, tot) sort(v[i].begin(), v[i].end(), cmp);
while(m --) {
scanf("%s", s);
if(*s=='Q') {
scanf("%d%d%d", &x, &a, &b);
ans = 0, nw = pos[x];
if(vis[nw]) Push_down(nw);
Dfs_point(x);
printf("%d\n", ans);
} else if(*s=='M') {
scanf("%d%d", &x, &val);
nw = pos[x];
if(vis[nw]) Push_down(nw);
c[x] = val-add[nw];
sort(v[nw].begin(), v[nw].end(), cmp);
} else if(*s=='C') {
scanf("%d%d", &x, &val);
nw = pos[x];
if(vis[nw]) Push_down(nw);
Point_add(x);
sort(v[nw].begin(), v[nw].end(), cmp);
} else if(*s=='W') {
scanf("%d%d", &x, &val);
nw = pos[x];
if(vis[nw]) Push_down(nw);
Point_modify(x);
sort(v[nw].begin(), v[nw].end(), cmp);
} else {
int x, y;
scanf("%d%d", &x, &y);
++ n, fa[n] = x, c[n] = y;
G.Add_edge(x, n);
if(v[pos[x]].size()==blo) {
++ tot, pos[n] = tot;
T.Add_edge(pos[x], tot);
v[tot].push_back(n);
} else {
nw = pos[x];
if(vis[nw]) Push_down(nw);
pos[n] = pos[x], c[n] = y-add[nw];
v[nw].push_back(n);
sort(v[nw].begin(), v[nw].end(), cmp);
}
}
}
return 0;
}