BZOJ 3083 - 遥远的国度
原题地址: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 ;
}
BZOJ 3083 - 遥远的国度的更多相关文章
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- BZOJ 3083: 遥远的国度 dfs序,树链剖分,倍增
今天再做一天树的题目,明天要开始专攻图论了.做图论十几天之后再把字符串搞搞,区域赛前再把计几看看. 3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 ...
- BZOJ 3083 遥远的国度 树链剖分
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ...
- bzoj 3083 遥远的国度——树链剖分+线段树维护子树信息
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 int 的范围是 2^31 - 1 ,所以权值是不是爆 int 了…… O( nlog ...
- BZOJ 3083 遥远的国度(树链剖分+线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3083 [题目大意] 链修改,子树最小值查询和换根操作 [题解] 树链剖分练习题. [代 ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- bzoj 3083 遥远的国度 —— 树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 换根后路径还是不变,子树分类讨论一下,树剖后线段树维护即可. 代码如下: #inclu ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- BZOJ 3083 遥远的国度 树链剖分+脑子
唉..又调了半天QWQ..为何读入挂了.....莫非读入是反着的????据ywy学长所言如是...OvO震惊 这啥骚题啊...还要换根...不过清明讲过...(然鹅我现在才做... 先随便选个点(比如 ...
随机推荐
- 2015 WEB前端学习路线图
2015 WEB前端学习路线图,欢迎小伙伴补充 @落雨
- JS中的间歇(周期)调用setInterval()与超时(延迟)调用setTimeout()相关总结
超时调用需要使用window.setTimeout(code,millisec)方法 它接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前需要等待多少毫秒).其中第一个参数可以是一个包含JS ...
- 禁止触屏滑动touchmove方法介绍
在移动端页面开发中,有时需要禁止用户滑动屏幕,搜索了好久才找到移动终端的touch事件,touchstar,touchmove,touchend. 阻止滚动 一些移动设备有缺省的touchmove行为 ...
- centos mysql 操作
安装mysqlyum -y install mysql-server 修改mysql配置 vi /etc/my.cnf 这里会有很多需要注意的配置项,后面会有专门的笔记 暂时修改一下编码(添加在密码下 ...
- Unity3D 错误,nativeVideoFrameCallback解决方法。
原地址:http://blog.csdn.net/alking_sun/article/details/23684733 Unity3D在打包安卓应用的时候,一打开游戏就闪退,接入LogCat之后发现 ...
- ASP.NET MVC 3和Razor中的@helper 语法
原文:http://kb.cnblogs.com/page/102191/ ASP.NET MVC 3支持一项名为"Razor"的新视图引擎选项(除了继续支持/加强现有的.aspx ...
- KMP高质量代码实现详解
KMP算法 对于KMP算法我分为两个部分说明,第一部分是算法部分,介绍KMP算法的算法思想:第二部分是实现部分,介绍一种厉害的实现代码以及代码注释.当然了由于本文主要介绍怎么实现故而先分析实现,对KM ...
- foreach的参数不是数组:Warning: Invalid argument supplied for foreach
Warning: Invalid argument supplied for foreach() 问题Warning: Invalid argument supplied for foreach() ...
- C# 获取windows特殊路径
虽然是古老的问题,最近用到这个,查一下还不少东东呐 一.使用Environment.SpecialFolder 该方法最简单,直接使用即可,只是提供的特殊路径比较少. (1)使用方法:string p ...
- 关于Try/Catch 代码块
应当放在Try/Catch 代码块中的常见任务包括连接到一个数据库或与其交互.处理文件.调用Web 服务. 老实说,我这人很少有打破沙锅问到底的精神.不过昨晚听一技术人员跟他的项目经理说要在程序中使用 ...