BZOJ 3083 - 遥远的国度

原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3083

说话间又一个多月过去了。。该来除除草了,每天都是训练、没效率,训练、没效率。。省选考得不好不说了=-继续努力吧

题目大意:维护一棵有根树,支持三个操作:换根; 一条链上都改为一个值; 求某个子树的Min

算法分析:
裸的动态树问题,非常简单啦。只涉及链上和子树操作,树的形态没有改变,所以用剖分来搞。就按照最开始给定的那个根剖分,得到一个剖分序。在换根之后查子树的时候注意一件事情,就是在最早的定根的形态中,现在的根如果在要查询的那个子树的根的某个儿子的子树上的话,就需要查询整个树除去这个儿子的子树的最小值,否则就是原来的那个子树的最小值。至于怎么判断,我用剖分序乱搞的=-

参考代码:

  1 //date 20140521
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 const int maxn = 105000;
  6 const int INF = 0x7FFFFFFF;
  7 
  8 template <typename T> inline void swap(T &a, T &b){T x = a; a = b; b = x;}
  9 inline int innew(int &a, int b){if(a < b){a = b; return 1;} return 0;}
 10 inline int denew(int &a, int b){if(a > b){a = b; return 1;} return 0;}
 11 inline int min(int a, int b){return a < b ? a : b;}
 12 
 13 inline int getint()
 14 {
 15     int ans(0); char w = getchar();
 16     while(w < '0' || '9' < w) w = getchar();
 17     while('0' <= w && w <= '9')
 18     {
 19         ans = ans * 10 + w - '0';
 20         w = getchar();
 21     }
 22     return ans;
 23 }
 24 
 25 int n, m, root;
 26 struct edge
 27 {
 28     int v, next;
 29 }E[maxn << 1];
 30 int nedge, a[maxn], num[maxn];
 31 
 32 inline void add(int u, int v)
 33 {
 34     E[++nedge].v = v;
 35     E[nedge].next = a[u];
 36     a[u] = nedge;
 37 }
 38 
 39 int dpt[maxn], p[maxn], size[maxn], hp[maxn], hs[maxn];
 40 int order[maxn], ps[maxn], ped[maxn];
 41 
 42 inline void dfs_one(int v0)
 43 {
 44     static int d[maxn], now[maxn];
 45     int last, i, j;
 46     memcpy(now, a, sizeof a);
 47     d[last = dpt[v0] = size[v0] = 1] = v0;
 48     while(last)
 49     {
 50         if(!(j = now[i = d[last]]))
 51         {
 52             if((--last) && (size[d[last]] += size[i], size[hs[d[last]]] < size[i]))
 53                 hs[d[last]] = i;
 54             continue;
 55         }
 56         if(p[i] != E[j].v) dpt[d[++last] = E[j].v] = dpt[p[E[j].v] = i] + (size[E[j].v] = 1);
 57         now[i] = E[j].next;
 58     }
 59 }
 60 
 61 inline void dfs_two(int v0)
 62 {
 63     static int d[maxn], now[maxn];
 64     int last, i, j, tot;
 65     d[last = 1] = order[ps[v0] = ped[v0] = tot = 1] = v0;
 66     memset(now, 0xFF, sizeof now);
 67     for(int i = 1; i <= n; ++i) hp[i] = i;
 68     while(last)
 69     {
 70         if(!(j = now[i = d[last]]))
 71         {
 72             if(--last) innew(ped[d[last]], ped[i]);
 73             continue;
 74         }
 75         if(j == -1)
 76         {
 77             if(hs[i]) hp[d[++last] = order[ps[hs[i]] = ped[hs[i]] = ++tot] = hs[i]] = hp[i];
 78             now[i] = a[i]; continue;
 79         }
 80         if(E[j].v != hs[i] && E[j].v != p[i]) d[++last] = order[ps[E[j].v] = ped[E[j].v] = ++tot] = E[j].v;
 81         now[i] = E[j].next;
 82     }
 83 }
 84 
 85 struct Segment_Tree
 86 {
 87     struct node
 88     {
 89         node *s[2];
 90         int l, r, Min, cov;
 91         node(){}
 92         int cover(int v){Min = v; cov = 1;}
 93         void pushdown()
 94         {
 95             if(cov && l < r){s[0]->cover(Min); s[1]->cover(Min);}
 96             cov = 0; 
 97         }
 98         void update(){ Min = min(s[0]->Min, s[1]->Min);}
 99     }*root, pond[maxn << 1];
100     int stop;
101     
102     void change(node *p, int l, int r, int v)
103     {
104         if(l <= p->l && p->r <= r){p->cover(v); return;}
105         p->pushdown();
106         int mid = (p->l + p->r) >> 1;
107         if(l <= mid) change(p->s[0], l, r, v);
108         if(r >  mid) change(p->s[1], l, r, v);
109         p->update();
110     }
111     
112     int query(node *p, int l, int r)
113     {
114         if(l <= p->l && p->r <= r){return p->Min;}
115         p->pushdown();
116         int mid = (p->l + p->r) >> 1;
117         int ans = INF;
118         if(l <= mid) denew(ans, query(p->s[0], l, r));
119         if(r >  mid) denew(ans, query(p->s[1], l, r));
120         return ans;
121     }
122     
123     node *build(int l, int r)
124     {
125         node *p = &pond[stop++];
126         p->s[0] = p->s[1] = NULL; p->cov = 0; p->l = l; p->r = r;
127         if(l == r) {p->Min = num[order[l]]; return p;}
128         int mid = (l + r) >> 1;
129         p->s[0] = build(l, mid);
130         p->s[1] = build(mid + 1, r);
131         p->update();
132         return p;
133     }
134     
135     void preset(){stop = 0; root = build(1, n);}
136     
137     int get_min(int l, int r)
138     {
139         if(l > r) swap(l, r);
140         return query(root, l, r);
141     }
142     
143     void change(int l, int r, int v)
144     {
145         if(l > r) swap(l, r);
146         change(root, l, r, v);
147     }
148 }MEOW;
149 
150 inline void reroot(int r){root = r;}
151 inline void change(int x, int y, int v)
152 {
153     int x0 = x, y0 = y;
154     while(hp[x0] != hp[y0])
155     {
156         if(dpt[hp[x0]] > dpt[hp[y0]])
157         {
158             MEOW.change(ps[hp[x0]], ps[x0], v);
159             x0 = p[hp[x0]];
160         }else{
161             MEOW.change(ps[hp[y0]], ps[y0], v);
162             y0 = p[hp[y0]];
163         }
164     }
165     MEOW.change(ps[x0], ps[y0], v);
166 }
167 inline int query(int x)
168 {
169     if(x == root) return MEOW.root->Min;
170     int x0 = x, r = root, sgn = 1, tp = 0;
171     if(hp[x0] == hp[r] && dpt[r] > dpt[x]) sgn = 0;
172     while(hp[x0] != hp[r])
173     {
174         if(dpt[hp[x0]] > dpt[hp[r]]) {sgn = 1; break;}
175         if(p[hp[r]] == x0) tp = hp[r];
176         sgn = 0; r = p[hp[r]];
177     }
178     if(dpt[r] < dpt[x]) sgn = 1;
179     if(sgn) return MEOW.get_min(ps[x], ped[x]);
180     if(r != x0) tp = hs[x0];
181     int ans = MEOW.get_min(1, ps[tp] - 1);
182     if(ped[tp] != n) denew(ans, MEOW.get_min(ped[tp] + 1, n));
183     return ans;
184 }
185 
186 int main()
187 {
188     freopen("bzoj.in", "r", stdin);
189     freopen("bzoj.out", "w", stdout);
190     
191     n = getint(); m = getint();
192     for(int i = 1; i < n; ++i)
193     {
194         int x = getint(), y = getint();
195         add(x, y); add(y, x);
196     }
197     for(int i = 1; i <= n; ++i) num[i] = getint() - 1;
198     root = getint();
199     dfs_one(root); dfs_two(root);
200     MEOW.preset();
201     for(int i = 1; i <= m; ++i)
202     {
203         int k, x, y, v;
204         k = getint();
205         switch(k)
206         {
207             case 1: x = getint(); reroot(x); break;
208             case 2: x = getint(); y = getint(); v = getint() - 1; change(x, y, v); break;
209             case 3: x = getint(); printf("%u\n", (unsigned)query(x) + 1u); break;
210         }
211     }
212     return 0;
213 }

 

posted on 2014-05-21 22:09  SnowyJone  阅读(774)  评论(0编辑  收藏  举报