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 }

 

你可能感兴趣的:(ZOJ)