3083: 遥远的国度

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 797  Solved: 181
[Submit][Status]

Description

描述
zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成
了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有
一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的
话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但
zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

Input

第1行两个整数n m,代表城市个数和操作数。
第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
第n+1行,有n个整数,代表所有点的初始防御值。
第n+2行一个整数 id,代表初始的首都为id。
第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数
p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数
id,代表询问以城市id为根的子树中的最小防御值。

Output

对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

Sample Input

3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1

Sample Output

1
2
3
4
提示
对于20%的数据,n<=1000 m<=1000。
对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。
 
 
 

思路来自hja,劲爆的读入优化来自zhonghaoxi,基本自己没想什么,还Wa了很久。

主要就是树链剖分。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 110000
#define lch (now<<1)
#define rch (now<<1^1)
typedef long long qword;
#ifdef unix
#define LL "%d"
#else
#define LL "%I64d"
#endif const int BUF_SIZE = ;
char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + ;
#define PTR_NEXT() \
{ \
buf_s ++; \
if (buf_s == buf_t) \
{ \
buf_s = buf; \
buf_t = buf + fread(buf, , BUF_SIZE, stdin); \
} \
} #define readint(_n_) \
{ \
while (*buf_s != '-' && !isdigit(*buf_s)) \
PTR_NEXT(); \
bool register _nega_ = false; \
if (*buf_s == '-') \
{ \
_nega_ = true; \
PTR_NEXT(); \
} \
int register _x_ = ; \
while (isdigit(*buf_s)) \
{ \
_x_ = _x_ * + *buf_s - ''; \
PTR_NEXT(); \
} \
if (_nega_) \
_x_ = -_x_; \
(_n_) = (_x_); \
}
int n,m;
int val_t[MAXN];
//segment_tree{{{
struct segt
{
int l,r,val;
int tag;
}tree[MAXN*];
int ptr[MAXN];
void down(int now)
{
if (tree[now].tag!=INF)
{
tree[lch].val=tree[rch].val=tree[lch].tag=tree[rch].tag=tree[now].tag;
tree[now].tag=INF;
}
}
void update(int now)
{
if (tree[now].l==tree[now].r)return ;
tree[now].val=min(tree[lch].val,tree[rch].val);
}
void build_tree(int now,int l,int r)
{
tree[now].l=l;
tree[now].r=r;
tree[now].tag=INF;
if (l==r){
ptr[l]=now;
tree[now].val=val_t[l];
return;
}
int mid=(l+r)>>;
build_tree(lch,l,mid);
build_tree(rch,mid+,r);
update(now);
}
/*
void set_val(int pos,int val)
{
pos=ptr[pos];
tree[pos].val=val;
while (pos)
{
update(pos);
pos>>=1;
}
}*/
void set_seg(int now,int l,int r,int val)
{
down(now);
if (tree[now].l==l&&tree[now].r==r)
{
tree[now].val=val;
tree[now].tag=val;
return ;
}
int mid=(tree[now].l+tree[now].r)>>;
if (r<=mid)
{
set_seg(lch,l,r,val);
update(now);
return ;
}
if (mid<l)
{
set_seg(rch,l,r,val);
update(now);
return ;
}
set_seg(lch,l,mid,val);
set_seg(rch,mid+,r,val);
update(now); }
int query_min(int now,int l,int r)
{
down(now);
if (tree[now].l==l&&tree[now].r==r)
{
return tree[now].val;
}
int mid;
mid=(tree[now].l+tree[now].r)>>;
if (r<=mid)
{
return query_min(lch,l,r);
}
if (mid<l)
{
return query_min(rch,l,r);
}
return min(query_min(lch,l,mid),query_min(rch,mid+,r));
}
//}}}
struct Edge
{
int np;
Edge *next;
}E[MAXN*],*V[MAXN];
int root,tope=-;
void addedge(int x,int y)
{
E[++tope].np=y;
E[tope].next=V[x];
V[x]=&E[tope];
}
int dfn[MAXN],l[MAXN],fa[MAXN],inp[MAXN],oup[MAXN];
int depth[MAXN];
int cnt=;
int siz_s[MAXN],son[MAXN];
int siz_t[MAXN];
int top[MAXN];
int dfs(int now,int dep)
{
Edge *ne;
int t;
siz_s[now]=;
siz_t[now]=;
depth[now]=dep;
for (ne=V[now];ne;ne=ne->next)
{
if (fa[now]!=ne->np)
{
fa[ne->np]=now;
t=dfs(ne->np,dep+);
siz_t[now]+=t;
if (t>siz_s[now])
{
siz_s[now]=t;
son[now]=ne->np;
}
}
}
return siz_t[now];
}
void dfs2(int now,int tp)
{
Edge *ne;
dfn[now]=++cnt;
inp[now]=cnt;
l[cnt]=val_t[now];
top[now]=tp;
if (son[now])dfs2(son[now],tp);
for (ne=V[now];ne;ne=ne->next)
{
if (fa[now]!=ne->np&&son[now]!=ne->np)
{
dfs2(ne->np,ne->np);
}
}
oup[now]=cnt;
}
int jump[][MAXN],topj;
void init_lca()
{
int i,j;
for (i=;i<=n;i++)jump[][i]=fa[i];
bool flag=true;
for (i=;i<&&flag;i++)
{
flag=false;
topj=i;
for (j=;j<=n;j++)
{
jump[i][j]=jump[i-][jump[i-][j]];
if (jump[i][j]!=root)flag=true;
}
}
}
void swim(int &x,int l)
{
int i=;
while (l)
{
if (l&)x=jump[i][x];
i++;
l>>=;
}
}
int lca(int x,int y)
{
if (depth[x]<depth[y])
{
swim(y,depth[y]-depth[x]);
}
if (depth[x]>depth[y])
{
swim(x,depth[x]-depth[y]);
}
if (x==y)return x;
for (int i=topj;i>=;i--)
{
if (jump[i][x]!=jump[i][y])
{
x=jump[i][x];
y=jump[i][y];
}
}
return fa[x];
}
int id;
int main()
{
freopen("input.txt","r",stdin);
//freopen("output2.txt","w",stdout);
//scanf("%d%d",&n,&m);
readint(n);
readint(m);
int i,j,k,x,y,z;
int a;
for (i=;i<n;i++)
{
//scanf("%d%d",&x,&y);
readint(x);
readint(y);
addedge(x,y);
addedge(y,x);
}
root=;
fa[root]=root;
dfs(root,);
dfs2(root,root);
init_lca();
for (i=;i<=n;i++)
{
readint(x);
//scanf("%d",&x);
val_t[dfn[i]]=x;
}
build_tree(,,cnt);
readint(id);
//scanf("%d",&id);
int opt,ans;
//cout<<"a";
for (i=;i<m;i++)
{
//scanf("%d",&opt);
readint(opt);
if (opt==)
{
//scanf("%d",&id);
readint(id);
}
if (opt==)
{
//scanf("%d%d%d",&x,&y,&z);
readint(x);
readint(y);
readint(z);
while (top[x]!=top[y])
{
if (depth[top[x]]<depth[top[y]])swap(x,y);
set_seg(,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
if (dfn[x]<dfn[y])
{
set_seg(,dfn[x],dfn[y],z);
}else
{
set_seg(,dfn[y],dfn[x],z);
}
}
if (opt==)
{
//scanf("%d",&x);
readint(x);
if (x==id)
{
ans=query_min(,,n);
printf("%d\n",ans);
continue;
}
if (x==root)
{
LABEL2:
y=id;
/* for (j=topj;j>=0;j--)
{
if (jump[j][y]!=x)
{
y=jump[j][y];
}
}*/
swim(y,depth[y]-depth[x]-);
ans=INF;
if (inp[y]!=)ans=query_min(,,inp[y]-);
if (oup[y]!=n)ans=min(ans,query_min(,oup[y]+,n));
printf("%d\n",ans);
continue;
}
if (depth[x]>=depth[id])
{
LABEL1:
ans=query_min(,inp[x],oup[x]);
printf("%d\n",ans);
continue;
}
if (lca(x,id)==x)
{
/* ans=INF;
ans=query_min(1,1,inp[x]);
if (oup[x]!=n)ans=min(ans,query_min(1,oup[x]+1,n));
printf("%d\n",ans);*/
goto LABEL2;
continue;
}else
{
goto LABEL1;
}
}
// cout<<opt<<" "<<x<<" "<<y<<endl;
} }

BZOJ 3083 遥远的国度 树链剖分的更多相关文章

  1. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  2. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  3. BZOJ 3083 遥远的国度 树链剖分+线段树

    有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...

  4. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  5. bzoj 3083 遥远的国度 —— 树链剖分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 换根后路径还是不变,子树分类讨论一下,树剖后线段树维护即可. 代码如下: #inclu ...

  6. bzoj 3083 遥远的国度——树链剖分+线段树维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 int 的范围是 2^31 - 1 ,所以权值是不是爆 int 了…… O( nlog ...

  7. BZOJ 3083 遥远的国度 树链剖分+脑子

    唉..又调了半天QWQ..为何读入挂了.....莫非读入是反着的????据ywy学长所言如是...OvO震惊 这啥骚题啊...还要换根...不过清明讲过...(然鹅我现在才做... 先随便选个点(比如 ...

  8. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  9. 【bzoj3083】遥远的国度 树链剖分+线段树

    题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...

随机推荐

  1. iBatis自动生成的主键 (Oracle,MS Sql Server,MySQL)【转】

    iBatis的sqlMap配置文件的selectKey元素有个type属性,可以指定pre或者post表示前生成(pre)还是后生成(post). Oracle设置 <!-- Oracle SE ...

  2. 条带深度 队列深度 NCQ IOPS

    http://blog.csdn.net/striping/article/details/17449653 IOPS 即I/O per second,即每秒进行读写(I/O)操作的次数,多用于数据库 ...

  3. [MySQL 5.6] 初识5.6的optimizer trace

      在MySQL5.6中,支持将执行的SQL的查询计划树记录下来,目前来看,即使对于非常简单的查询,也会打印出冗长的查询计划,看起来似乎不是很可读,不过对于一个经验丰富,对查询计划的生成过程比较了解的 ...

  4. oracle在敏感操作前创建还原点

    我们都知道,在vmware虚拟机中有一个拍摄快照的功能,我们可以把系统此时的状态保存下来,一方后面遇到不测事件,也好将系统还原,oracle中也有类似功能. 首先创建一张学生表: 向学生表中插入一条数 ...

  5. oracle redo日志维护

    环境 OS:Red Hat Linux As 5 DB:10.2.0.1 1.添加日志组 alter database add logfile group 4 ('/u01/app/oracle/or ...

  6. [转载] CMake Official Tutorial——教程还是官方的好

    CMake官方教程传送门:https://cmake.org/cmake-tutorial/ 以下的内容跟官方教程基本一致,少数地方根据自己的测试有所改动: A Basic Starting Poin ...

  7. 【工具篇】notepad++

    一直都是使用notepad++来写程序,感觉比UE好用多了,没有UE那么重.前段时间网上还做了一个调查,notepad++在国外使用排行还是非常高的,在国内也是很流行.以下记录一些比较实用的技巧. 一 ...

  8. 图解数据结构树之AVL树

    AVL树(平衡二叉树): AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.在AVL树中任何节点的两个子 ...

  9. c、c++混编实现查询本地IP地址

    一.思路 1.要想得到本地IP地址,可以通过本机名来查询,所以首先得得到本机名. 2.牵涉到IP地址,首先想到牵涉到网络协议,因此得加载套接字协议,所以先使用WSAStartup函数完成对Winsoc ...

  10. DisUnity——Unity3D反编译资源提取利刃

    1.资源 软件及项目源码地址:https://github.com/ata4/disunity/releases 2.使用方法: 将待反编译的文件放入文件夹中:如:E:\Demo\ 在disunity ...