BZOJ 3083 遥远的国度 树链剖分
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
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
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 遥远的国度 树链剖分的更多相关文章
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- BZOJ 3083 遥远的国度 树链剖分+线段树
有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- bzoj 3083 遥远的国度 —— 树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 换根后路径还是不变,子树分类讨论一下,树剖后线段树维护即可. 代码如下: #inclu ...
- bzoj 3083 遥远的国度——树链剖分+线段树维护子树信息
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 int 的范围是 2^31 - 1 ,所以权值是不是爆 int 了…… O( nlog ...
- BZOJ 3083 遥远的国度 树链剖分+脑子
唉..又调了半天QWQ..为何读入挂了.....莫非读入是反着的????据ywy学长所言如是...OvO震惊 这啥骚题啊...还要换根...不过清明讲过...(然鹅我现在才做... 先随便选个点(比如 ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- 【bzoj3083】遥远的国度 树链剖分+线段树
题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...
随机推荐
- mysql in 的两种使用方法
简述MySQL 的in 的两种使用方法: 他们各自是在 in keyword后跟一张表(记录集).以及在in后面加上字符串集. 先讲后面跟着一张表的. 首先阐述三张表的结构: s(sno,sname. ...
- GCC 编绎选项 转
gcc提供了大量的警告选项,对代码中可能存在的问题提出警告,通常可以使用-Wall来开启以下警告: -Waddress -Warray-bounds (only with -O2) ...
- vc++ 最小化到托盘的详细实现
在VC++中,想实现将MFC最小化到系统托盘,需要调用NOTIFYICONDATA类,并注册相应的消息,以下详细讲解如何实现: 1.声明一个NOTIFYICONDATA类,也就是NOTIFYICOND ...
- UTF-8 BOM对PHP的影响
今天在用notepad++写代码时 载入一个frameset框架模版后 在页面上一直不显示该页面,查看源码后都正常.然后索性把里面东西全删掉 随便写了几个测试文字可以正常显示. 折腾了好长时间,最后偶 ...
- ASP.NET+ashx+jQuery动态添加删除表格
aspx: <script src="../script/jquery-1.4.4.min.js" type="text/javascript" lang ...
- mysql开启函数功能
输入 show variables like '%func%'; 命令 会看到 log_bin_trust_function_creators 的状态,如果是OFF表示自定义函数功能是关闭的 输入命令 ...
- MES项目中出现的一个事务嵌套的使用场景
昨天在MES项目中,需要在业务逻辑的几个关键点记录错误信息,需要把错误信息写入数据表. 但是由于整个业务逻辑都是包在一个事务模板里面的 比如这样的: WhhTransactionTemplate tr ...
- Android Studio SDK Manager无法正常下载如何设置
博客分类: Linux 零散小知识 Android那点事 AndroidStudioSDKManager 一方面在/etc/hosts中设置: #Google主页 203.208.46.146 ww ...
- 深入理解自定义ListView
深入理解自定义ListView ListView原理 他是一个系统的原生控件,用列表的形式来显示内容.如果内容过过有1000条左右,我们可以通过手势的上下滑动来查看数据.ListView也不是爆出OO ...
- 'EntityValidationErrors' property for more details
很多小猿遇到这个Exception 的时候,都会有点无厘头.这个时候最好try-- catch下,找到出错的地方.本人习惯在页面上加个lable标签,把exc msg(exception messag ...