[poi2007]mem

题意:给定点数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
", ans[i]); 
 99 }
100 
101 int main(){
102     while (scanf("%d", &n) != EOF){
103           init();
104           solve();
105     }
106     return 0;
107 }
View Code

code(手写链表):

  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 M0(x)  memset(x, 0, sizeof(x))
 16 #define Inf  0x7fffffff
 17 using namespace std;
 18 const int maxn = 300002;
 19 struct node{
 20        int v, next;    
 21 } e[maxn * 3];
 22 struct qes{
 23        int v, t, next;     
 24 } q[maxn << 2];
 25 int n, m, ans[maxn<<1], last[maxn], lastq[maxn], tot, len;
 26 int pos[maxn<<1];
 27 
 28 inline void R(int &ret){
 29     ret = 0;
 30     bool ok = 0;
 31     for( ; ;){
 32         int c = getchar();
 33         if (c >= '0' && c <= '9') ret = (ret << 3) + (ret << 1) + c - '0', ok = 1;
 34         else if (ok) return;
 35     }
 36 }
 37 
 38 inline void add(const int& u,const int& v){
 39     e[tot] = (node){v, last[u]}, last[u] = tot++;
 40 }
 41 
 42 inline void add_ask(const int& u,const int& v,const int& t){
 43     q[len] = (qes){v, t, lastq[u]}, lastq[u] = len++;
 44 }
 45 
 46 void init(){
 47      int u, v;
 48      memset(last, -1, sizeof(last));
 49      memset(lastq, -1, sizeof(lastq));
 50      len = tot = 0;
 51      for (int i = 1; i < n; ++i)
 52           R(u), R(v), add(u, v), add(v, u);
 53      char op[10];
 54      R(m);
 55      int nm = n + m - 1;
 56      int n1 = 1;
 57      for (int i = 1; i <= nm; ++i){
 58            scanf("%s", op);
 59            if (op[0] == 'A') ++n1; 
 60            pos[i] = n1;
 61            if (op[0] == 'W')
 62                   R(u), add_ask(u, -1, i);
 63            else {
 64                   R(u), R(v);
 65                   add_ask(u, v, i), add_ask(v, u, i);
 66            }
 67      }
 68 //     cout << n1 << endl;
 69 }
 70 
 71 int vis[maxn], s[maxn], dep[maxn];
 72 void update(int x,const int& v){
 73      for (; x<=n; x += x&(-x)) s[x] += v;
 74 }
 75 
 76 int query(int x){
 77     int res = 0;
 78     for (; x>0; x -= x&(-x)) res += s[x];
 79     return  res;
 80 }
 81 
 82 void  dfs(const int& u){
 83       vis[u] = 1;
 84       for (int p = lastq[u]; ~p; p = q[p].next) 
 85           if (q[p].v != -1 && vis[q[p].v])  update(pos[q[p].t], 1);
 86       for (int p = lastq[u]; ~p; p = q[p].next) 
 87           if (q[p].v == -1)  ans[q[p].t] = dep[u] - query(pos[q[p].t]);
 88       for (int p = last[u]; ~p; p = e[p].next) 
 89           if (!vis[e[p].v])  dep[e[p].v] = dep[u] + 1, dfs(e[p].v);
 90       for (int p = lastq[u]; ~p; p = q[p].next) 
 91           if (q[p].v != -1 && dep[q[p].v] < dep[u])  update(pos[q[p].t], -1);
 92 }
 93 
 94 void solve(){
 95      memset(ans, -1, sizeof(int) * (n+m+10));
 96      memset(vis, 0, sizeof(int) * (n+10));
 97      memset(s, 0, sizeof(int) * (n+10));
 98      dep[1] = 0;
 99      dfs(1);
100      int nm = n + m;
101      for (int i = 1; i < nm; ++i) 
102           if (ans[i] >= 0) printf("%d
", ans[i]); 
103 }
104 
105 int main(){
106 //    freopen("a.in", "r", stdin);
107 //    freopen("a.out", "w", stdout);
108     while (scanf("%d", &n) != EOF){
109           init();
110           solve();
111     }
112     return 0;
113 }
View Code

       

           

原文地址:https://www.cnblogs.com/yzcstc/p/4093876.html