【树链剖分】【线段树】bzoj3083 遥远的国度
记最开始的根为root,换根之后,对于当前的根rtnow和询问子树U而言,
①rtnow==U,询问整棵树
②fa[rtnow]==U,询问除了rtnow所在子树以外的整棵树
③rtnow在U的子树里,且距离大于1,询问除了rtnow的除了其祖先是U的儿子的祖先的子树以外的整棵树
④rtnow不在U的子树里,询问U的子树
对于③,在树链上跳跳就好了,也可以暴力,复杂度无法保证。
- #include<cstdio>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- #define N 100001
- #define INF 2147483647
- #define lson rt<<1,l,m
- #define rson rt<<1|1,m+1,r
- int v[N<<1],en,next[N<<1],first[N];
- void AddEdge(int U,int V)
- {
- v[++en]=V;
- next[en]=first[U];
- first[U]=en;
- }
- int n,m,root,a[N];
- int Ls[N],Rs[N],top[N],siz[N],fa[N],dep[N],tot,son[N],rtnow,Map[N];
- void dfs(int U)
- {
- siz[U]=1;
- for(int i=first[U];i;i=next[i])
- if(v[i]!=fa[U])
- {
- fa[v[i]]=U;
- dep[v[i]]=dep[U]+1;
- dfs(v[i]);
- siz[U]+=siz[v[i]];
- if(siz[v[i]]>siz[son[U]])
- son[U]=v[i];
- }
- }
- void dfs2(int U)
- {
- Ls[U]=++tot;
- Map[tot]=U;
- if(son[U])
- {
- top[son[U]]=top[U];
- dfs2(son[U]);
- }
- for(int i=first[U];i;i=next[i])
- if(v[i]!=fa[U]&&v[i]!=son[U])
- {
- top[v[i]]=v[i];
- dfs2(v[i]);
- }
- Rs[U]=tot;
- }
- int minv[N<<2],cov[N<<2];
- void pushdown(int rt)
- {
- if(cov[rt])
- {
- cov[rt<<1]=cov[rt<<1|1]=minv[rt<<1]=minv[rt<<1|1]=cov[rt];
- cov[rt]=0;
- }
- }
- void update(int ql,int qr,int v,int rt,int l,int r)
- {
- if(ql<=l&&r<=qr)
- {
- cov[rt]=minv[rt]=v;
- return;
- }
- pushdown(rt);
- int m=(l+r>>1);
- if(ql<=m) update(ql,qr,v,lson);
- if(m<qr) update(ql,qr,v,rson);
- minv[rt]=min(minv[rt<<1],minv[rt<<1|1]);
- }
- int query(int ql,int qr,int rt,int l,int r)
- {
- if(ql<=l&&r<=qr) return minv[rt];
- pushdown(rt);
- int m=(l+r>>1),res=INF;
- if(ql<=m) res=min(res,query(ql,qr,lson));
- if(m<qr) res=min(res,query(ql,qr,rson));
- return res;
- }
- void Update(int U,int V,int W)
- {
- int f1=top[U],f2=top[V],res=INF;
- while(f1!=f2)
- {
- if(dep[f1]<dep[f2])
- {
- swap(f1,f2);
- swap(U,V);
- }
- update(Ls[f1],Ls[U],W,1,1,n);
- U=fa[U];
- f1=top[U];
- }
- if(dep[U]>dep[V])
- swap(U,V);
- update(Ls[U],Ls[V],W,1,1,n);
- }
- int main()
- {
- // freopen("bzoj3083.in","r",stdin);
- int A,B,C,op;
- scanf("%d%d",&n,&m);
- for(int i=1;i<n;++i)
- {
- scanf("%d%d",&A,&B);
- AddEdge(A,B);
- AddEdge(B,A);
- }
- for(int i=1;i<=n;++i) scanf("%d",&a[i]);
- scanf("%d",&root);
- top[root]=root;
- dfs(root);
- dfs2(root);
- for(int i=1;i<=n;++i) update(Ls[i],Ls[i],a[i],1,1,n);
- for(;m;--m)
- {
- scanf("%d",&op);
- if(op==1) scanf("%d",&rtnow);
- else if(op==2)
- {
- scanf("%d%d%d",&A,&B,&C);
- Update(A,B,C);
- }
- else
- {
- scanf("%d",&A);
- if(A==rtnow)
- printf("%d\n",query(1,n,1,1,n));
- else if(fa[rtnow]==A)
- printf("%d\n",min(query(1,Ls[rtnow]-1,1,1,n),Rs[rtnow]==n?INF:query(Rs[rtnow]+1,n,1,1,n)));
- else if(Ls[rtnow]>=Ls[A]&&Ls[rtnow]<=Rs[A])
- {
- int U=rtnow;
- while(fa[top[U]]!=A&&top[U]!=top[A])
- U=fa[top[U]];
- if(fa[top[U]]!=A)
- U=Map[Ls[A]+1];
- else
- U=top[U];
- printf("%d\n",min(query(1,Ls[U]-1,1,1,n),Rs[U]==n?INF:query(Rs[U]+1,n,1,1,n)));
- }
- else
- printf("%d\n",query(Ls[A],Rs[A],1,1,n));
- }
- }
- return 0;
- }
【树链剖分】【线段树】bzoj3083 遥远的国度的更多相关文章
- 【bzoj3083】遥远的国度 树链剖分+线段树
题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
随机推荐
- POJ3169:Layout(差分约束)
Layout Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15705 Accepted: 7551 题目链接:http ...
- POJ2516:Minimum Cost(最小费用最大流)
Minimum Cost Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 19088 Accepted: 6740 题目链 ...
- Good Substrings CodeForces - 271D
You've got string s, consisting of small English letters. Some of the English letters are good, the ...
- jaspersoft中分组打印
一:前言 使用IReport已经四个月了,最近在做一个保镖,是要按照类型分类,并且这些类型要横着打印,最后还要算这个类型金额的总值,这张报表现是说需要用到子报表,最后和一个同事一起用group来分组做 ...
- bzoj1503 郁闷的出纳员 splay版
自己yy的写法 可能有点奇怪吧 详情看代码 还是蛮短的 #include<cstdio> #include<cstring> #include<algorithm> ...
- [bzoj4765]普通计算姬——分块
Brief Description 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权 值和.支持下列两种操作: 1 给定两个整数u,v, ...
- 用 C# 代码如何实现让你的电脑关机,重启,注销,锁定,休眠,睡眠
简介 本文讲述了用 C# 代码如何实现让你的电脑关机,重启,注销,锁定,休眠,睡眠. 如何实现 首先,使用 using 语句添加我们需要的命名空间: using System.Diagnostics; ...
- MySQL-based databases CVE-2016-6664 本地提权
@date: 2016/11/10 @author: dlive 0x00 前言 这个漏洞可以结合CVE-2016-6663使用提升权限到root 0x01 漏洞原文 # http://legalha ...
- 打包工具 Inno Setup 5
转载: http://www.360doc.com/content/13/0327/13/4221543_274235049.shtml
- UVA 10471 Gift Exchanging
题意:就5种盒子,给出每个盒子个数,盒子总数,每个人选择这个盒子的概率.求这个人选择哪个盒子取得第一个朋友的概率最大,最大多少 dp[N][sta]表示当前第N个人面临状态sta(选择盒子的状态可以用 ...