题意:给定点数n<=300000的一棵树,然后初始时每条边权值为1,接下来按照时间点先后顺序的n+m-1个操作,
操作有两种:
1.A a b 把a到b的边权改为0
2.W u 求1号点到u号点的路径权值和
思路:如果现在把题目简化为是在一条直线上的操作,每次在中间删除相邻边权值或者查询某个点到1号点的权值和
我们很容易想把询问离线,然后从1->n扫描1遍,然后用一个树状数组维护前缀和即可。。
到了本题利用dfs序显然就可以转化成线性模型,
具体的话
做到点u,
如果有一个操作1在(u, fa[u])的边,时间为t,那么在t时间点删除一个点
如果有一个操作2在u点,时间为t,那么就等价于查询1~u路径上的点数-t时间内删除的点数
回溯时把操作还原
code(stl):
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<algorithm> 8 #include<string> 9 #include<map> 10 #include<set> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<ctime> 15 #define x first 16 #define y second 17 #define M0(x) memset(x, 0, sizeof(x)) 18 #define vii vector<int>::iterator 19 #define vpi vector<pair<int, int> >::iterator 20 #define Inf 0x7fffffff 21 using namespace std; 22 typedef pair<int, int> pii; 23 const int maxn = 300002; 24 vector<int> e[maxn]; 25 vector<pii> q[maxn]; 26 int n, m, ans[maxn<<1]; 27 int pos[maxn<<1]; 28 29 inline void R(int &ret){ 30 ret = 0; 31 bool ok = 0; 32 for( ; ;){ 33 int c = getchar(); 34 if (c >= '0' && c <= '9') ret = (ret << 3) + (ret << 1) + c - '0', ok = 1; 35 else if (ok) return; 36 } 37 } 38 39 40 void init(){ 41 int u, v; 42 // for (int i = 1; i <= n; ++i) e[i].clear(), q[i].clear(); 43 pii tmp; 44 for (int i = 1; i < n; ++i) 45 R(u), R(v), e[u].push_back(v), e[v].push_back(u); 46 char op[10]; 47 R(m); 48 int nm = n + m - 1; 49 int n1 = 1; 50 for (int i = 1; i <= nm; ++i){ 51 scanf("%s", op); 52 if (op[0] == 'A') ++n1; 53 tmp.x = i; 54 pos[i] = n1; 55 if (op[0] == 'W') 56 R(u), tmp.y = -1, q[u].push_back(tmp); 57 else { 58 R(u), R(v); 59 tmp.y = v, q[u].push_back(tmp); 60 tmp.y = u, q[v].push_back(tmp); 61 } 62 } 63 // cout << n1 << endl; 64 } 65 66 int vis[maxn], s[maxn], dep[maxn]; 67 void update(int x,const int& v){ 68 for (; x<=n; x += x&(-x)) s[x] += v; 69 } 70 71 int query(int x){ 72 int res = 0; 73 for (; x>0; x -= x&(-x)) res += s[x]; 74 return res; 75 } 76 77 int ss; 78 void dfs(const int& u){ 79 vis[u] = 1; 80 for (vpi it = q[u].begin(); it != q[u].end(); ++it) 81 if (it->y != -1 && vis[it->y]) update(pos[it->x], 1); 82 for (vpi it = q[u].begin(); it != q[u].end(); ++it) 83 if (it->y == -1) ans[it->x] = dep[u] - query(pos[it->x]); 84 for (vii it = e[u].begin(); it != e[u].end(); ++it) 85 if (!vis[*it]) dep[*it] = dep[u] + 1, dfs(*it); 86 for (vpi it = q[u].begin(); it != q[u].end(); ++it) 87 if (it->y != -1 && dep[it->y] < dep[u]) update(pos[it->x], -1); 88 } 89 90 void solve(){ 91 memset(ans, -1, sizeof(int) * (n+m+10)); 92 memset(vis, 0, sizeof(int) * (n+10)); 93 memset(s, 0, sizeof(int) * (n+10)); 94 dep[1] = 0; 95 dfs(1); 96 int nm = n + m; 97 for (int i = 1; i < nm; ++i) 98 if (ans[i] >= 0) printf("%d\n", ans[i]); 99 } 100 101 int main(){ 102 while (scanf("%d", &n) != EOF){ 103 init(); 104 solve(); 105 } 106 return 0; 107 }