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

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

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

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

参考代码:

 //date 20140521
#include <cstdio>
#include <cstring> const int maxn = ;
const int INF = 0x7FFFFFFF; template <typename T> inline void swap(T &a, T &b){T x = a; a = b; b = x;}
inline int innew(int &a, int b){if(a < b){a = b; return ;} return ;}
inline int denew(int &a, int b){if(a > b){a = b; return ;} return ;}
inline int min(int a, int b){return a < b ? a : b;} inline int getint()
{
int ans(); char w = getchar();
while(w < '' || '' < w) w = getchar();
while('' <= w && w <= '')
{
ans = ans * + w - '';
w = getchar();
}
return ans;
} int n, m, root;
struct edge
{
int v, next;
}E[maxn << ];
int nedge, a[maxn], num[maxn]; inline void add(int u, int v)
{
E[++nedge].v = v;
E[nedge].next = a[u];
a[u] = nedge;
} int dpt[maxn], p[maxn], size[maxn], hp[maxn], hs[maxn];
int order[maxn], ps[maxn], ped[maxn]; inline void dfs_one(int v0)
{
static int d[maxn], now[maxn];
int last, i, j;
memcpy(now, a, sizeof a);
d[last = dpt[v0] = size[v0] = ] = v0;
while(last)
{
if(!(j = now[i = d[last]]))
{
if((--last) && (size[d[last]] += size[i], size[hs[d[last]]] < size[i]))
hs[d[last]] = i;
continue;
}
if(p[i] != E[j].v) dpt[d[++last] = E[j].v] = dpt[p[E[j].v] = i] + (size[E[j].v] = );
now[i] = E[j].next;
}
} inline void dfs_two(int v0)
{
static int d[maxn], now[maxn];
int last, i, j, tot;
d[last = ] = order[ps[v0] = ped[v0] = tot = ] = v0;
memset(now, 0xFF, sizeof now);
for(int i = ; i <= n; ++i) hp[i] = i;
while(last)
{
if(!(j = now[i = d[last]]))
{
if(--last) innew(ped[d[last]], ped[i]);
continue;
}
if(j == -)
{
if(hs[i]) hp[d[++last] = order[ps[hs[i]] = ped[hs[i]] = ++tot] = hs[i]] = hp[i];
now[i] = a[i]; continue;
}
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;
now[i] = E[j].next;
}
} struct Segment_Tree
{
struct node
{
node *s[];
int l, r, Min, cov;
node(){}
int cover(int v){Min = v; cov = ;}
void pushdown()
{
if(cov && l < r){s[]->cover(Min); s[]->cover(Min);}
cov = ;
}
void update(){ Min = min(s[]->Min, s[]->Min);}
}*root, pond[maxn << ];
int stop; void change(node *p, int l, int r, int v)
{
if(l <= p->l && p->r <= r){p->cover(v); return;}
p->pushdown();
int mid = (p->l + p->r) >> ;
if(l <= mid) change(p->s[], l, r, v);
if(r > mid) change(p->s[], l, r, v);
p->update();
} int query(node *p, int l, int r)
{
if(l <= p->l && p->r <= r){return p->Min;}
p->pushdown();
int mid = (p->l + p->r) >> ;
int ans = INF;
if(l <= mid) denew(ans, query(p->s[], l, r));
if(r > mid) denew(ans, query(p->s[], l, r));
return ans;
} node *build(int l, int r)
{
node *p = &pond[stop++];
p->s[] = p->s[] = NULL; p->cov = ; p->l = l; p->r = r;
if(l == r) {p->Min = num[order[l]]; return p;}
int mid = (l + r) >> ;
p->s[] = build(l, mid);
p->s[] = build(mid + , r);
p->update();
return p;
} void preset(){stop = ; root = build(, n);} int get_min(int l, int r)
{
if(l > r) swap(l, r);
return query(root, l, r);
} void change(int l, int r, int v)
{
if(l > r) swap(l, r);
change(root, l, r, v);
}
}MEOW; inline void reroot(int r){root = r;}
inline void change(int x, int y, int v)
{
int x0 = x, y0 = y;
while(hp[x0] != hp[y0])
{
if(dpt[hp[x0]] > dpt[hp[y0]])
{
MEOW.change(ps[hp[x0]], ps[x0], v);
x0 = p[hp[x0]];
}else{
MEOW.change(ps[hp[y0]], ps[y0], v);
y0 = p[hp[y0]];
}
}
MEOW.change(ps[x0], ps[y0], v);
}
inline int query(int x)
{
if(x == root) return MEOW.root->Min;
int x0 = x, r = root, sgn = , tp = ;
if(hp[x0] == hp[r] && dpt[r] > dpt[x]) sgn = ;
while(hp[x0] != hp[r])
{
if(dpt[hp[x0]] > dpt[hp[r]]) {sgn = ; break;}
if(p[hp[r]] == x0) tp = hp[r];
sgn = ; r = p[hp[r]];
}
if(dpt[r] < dpt[x]) sgn = ;
if(sgn) return MEOW.get_min(ps[x], ped[x]);
if(r != x0) tp = hs[x0];
int ans = MEOW.get_min(, ps[tp] - );
if(ped[tp] != n) denew(ans, MEOW.get_min(ped[tp] + , n));
return ans;
} int main()
{
freopen("bzoj.in", "r", stdin);
freopen("bzoj.out", "w", stdout); n = getint(); m = getint();
for(int i = ; i < n; ++i)
{
int x = getint(), y = getint();
add(x, y); add(y, x);
}
for(int i = ; i <= n; ++i) num[i] = getint() - ;
root = getint();
dfs_one(root); dfs_two(root);
MEOW.preset();
for(int i = ; i <= m; ++i)
{
int k, x, y, v;
k = getint();
switch(k)
{
case : x = getint(); reroot(x); break;
case : x = getint(); y = getint(); v = getint() - ; change(x, y, v); break;
case : x = getint(); printf("%u\n", (unsigned)query(x) + 1u); break;
}
}
return ;
}

最新文章

  1. AngularJS之指令中controller与link(十二)
  2. 【转】windows和linux中搭建python集成开发环境IDE
  3. Pragma如何分组
  4. 对unsigned int和int进行移位操作的区别
  5. 《Java数据结构与算法》笔记-CH2有序数组
  6. html页面布局 第8节
  7. Markdown入门指南-指间阁
  8. 判断UserAgent是否为手机
  9. Android 平滑图片加载和缓存库 Glide 使用详解
  10. EBS中使用JAVA方式发送HTML格式邮件
  11. 练习:javascript轮播图效果
  12. ASP.NET Core使用NLog记录日志到Microsoft Sql Server
  13. Windows之系统自带截屏快捷键
  14. [iOS]视图与UIVIew
  15. 38.Spring-spring和hibernate整合.md
  16. python 全栈开发,Day104(DRF用户认证,结算中心,django-redis)
  17. Java 6- Java 运算符
  18. 深入解析SQL Server高可用镜像实现原理
  19. Java基础笔记(1) 语言 JAVA的历史 Java的搭建环境
  20. webWorker

热门文章

  1. MYSQL导入导出.sql文件(转)
  2. Codeforces Round #271 (Div. 2) F ,E, D, C, B, A
  3. android SDK更新
  4. 异步等待的 Python 协程
  5. acdream1116 Gao the string!(扩展KMP)
  6. Office 2013 note
  7. Webpack+React配合开发
  8. Python 爬虫过程中的中文乱码问题
  9. (转)【移动开发】Android中三种超实用的滑屏方式汇总(ViewPager、ViewFlipper、ViewFlow)
  10. Linux中ping命令