记录编号 |
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;
- }
-