bzoj 2325: [ZJOI2011]道馆之战 (树链剖分+线段树)
来源:互联网 发布:淘宝电商怎么做 编辑:程序博客网 时间:2024/05/16 02:05
2325: [ZJOI2011]道馆之战
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1175 Solved: 429
[Submit][Status][Discuss]
Description
口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中
的每一个冰块都只能经过一次。当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才会被打开。三个冰
地分别如下:
当走出第三个冰地之后,就可以与馆主进行道馆战了。馆主发现这个难度太小,导致经常有挑战者能通过,为了加
大难度,将道馆分成了n个房间,每个房间中是两个冰块或障碍,表示一列冰地。任意两个房间之间均有且仅有一
条路径相连,即这n个房间构成一个树状结构。每个房间分成了A和B两个区域,每一区域都是一个薄冰块或者障碍
物。每次只能移动到相邻房间的同一类区域(即若你现在在这个房间的A区域,那么你只能移动到相邻房间的A区域)
或这个房间的另一区域。现在挑战者从房间u出发,馆主在房间v,那么挑战者只能朝接近馆主所在房间的方向过去
。一开始挑战者可以在房间u的任意一个冰块区域内。如果挑战者踩过的冰块数达到了最大值(即没有一种方案踩过
的冰块数更多了),那么当挑战者走到最后一个冰块上时,他会被瞬间传送到馆主面前与馆主进行道馆战。自从馆
主修改规则后已经经过了m天,每天要么是有一个挑战者来进行挑战,要么就是馆主将某个房间进行了修改。对于
每个来的挑战者,你需要计算出他若要和馆主进行战斗需要经过的冰块数。
Input
第一行包含两个正整数n和m。第2行到第n行,每行包含两个正整数x和y,表示一条连接房间x和房间y的边。房间编
号为1…n。接下来n行,每行包含两个字符。第n + k行表示房间k的两个区域,第一个字符为A区域,第二个字符为
B区域。其中“.”(ASCII码为46)表示是薄冰块,“#”(ASCII码为35)表示是障碍物。最后的m行,每行一个操作:
l C u s:将房间u里的两个区域修改为s。
l Q u v:询问挑战者在房间u,馆主在房间v时,挑战者能与馆主进行挑战需要踩的冰块数。如果房间u的两个区域
都是障碍物,那么输出0。
N≤ 30 000
M ≤ 80 000
Output
包含若干行,每行一个整数。即对于输入中的每个询问,依次输出一个答案。
Sample Input
5 3
1 2
2 3
2 4
1 5
.#
..
#.
.#
..
Q 5 3
C 1 ##
Q 4 5
1 2
2 3
2 4
1 5
.#
..
#.
.#
..
Q 5 3
C 1 ##
Q 4 5
Sample Output
6
3
3
HINT
Source
Day2
题解:树链剖分+线段树
线段树维护从左上到右上,从左上到右下,从左下到右上,从左下到右下走过冰块的最大值
以及从一段区间的左上,左下,右上,右下出发分别能达到能到达的最远距离。
剩下的就是树链剖分的问题啦。
注意从x->lca(x,y)得到的信息,需要进行适当的调整,再与lca(x,y)->y合并。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 30003#define inf 1000000000using namespace std;struct data{ int l1,l2,r1,r2; int d1,d2,d3,d4;}tr[N*4];char s[N][3];int n,m,point[N*2],nxt[N*2],v[N*2],tot,sz;int belong[N],pos[N],size[N],q[N],son[N],deep[N],fa[N];void add(int x,int y){ tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}void dfs(int x,int f){ size[x]=1; deep[x]=deep[f]+1; for (int i=point[x];i;i=nxt[i]){ if (v[i]==f) continue; fa[v[i]]=x; dfs(v[i],x); size[x]+=size[v[i]]; if (size[v[i]]>size[son[x]]) son[x]=v[i]; }}void dfs1(int x,int chain){ pos[x]=++sz; q[sz]=x; belong[x]=chain; if (!son[x]) return; dfs1(son[x],chain); for (int i=point[x];i;i=nxt[i]) if(v[i]!=son[x]&&v[i]!=fa[x]) dfs1(v[i],v[i]);}data update(data x,data y){ data a; a.d1=max(x.d1+y.d1,x.d2+y.d3); if (a.d1<0) a.d1=-inf; a.d2=max(x.d2+y.d4,x.d1+y.d2); if (a.d2<0) a.d2=-inf; a.d3=max(x.d3+y.d1,x.d4+y.d3); if (a.d3<0) a.d3=-inf; a.d4=max(x.d3+y.d2,x.d4+y.d4); if (a.d4<0) a.d4=-inf; a.l1=x.l1; a.l2=x.l2; a.r1=y.r1; a.r2=y.r2; a.l1=max(a.l1,max(x.d1+y.l1,x.d2+y.l2)); if (a.l1<0) a.l1=-inf; a.l2=max(a.l2,max(x.d4+y.l2,x.d3+y.l1)); if (a.l2<0) a.l2=-inf; a.r1=max(a.r1,max(y.d1+x.r1,y.d3+x.r2)); if (a.r1<0) a.r1=-inf; a.r2=max(a.r2,max(y.d2+x.r1,y.d4+x.r2)); if (a.r2<0) a.r2=-inf; return a;}void build(int now,int l,int r){ if (l==r) { int x=q[l]; tr[now].d1=tr[now].d2=tr[now].d3=tr[now].d4=-inf; tr[now].l1=tr[now].l2=tr[now].r1=tr[now].r2=-inf; if (s[x][0]=='.') tr[now].d1=tr[now].l1=tr[now].r1=1; if (s[x][1]=='.') tr[now].d4=tr[now].l2=tr[now].r2=1; if (s[x][1]=='.'&&s[x][0]=='.') tr[now].d2=tr[now].d3=tr[now].l1=tr[now].l2=tr[now].r1=tr[now].r2=2; //cout<<tr[now].l1<<" "<<tr[now].l2<<" "<<tr[now].r1<<" "<<tr[now].r2<<endl; return; } int mid=(l+r)/2; build(now<<1,l,mid); build(now<<1|1,mid+1,r); tr[now]=update(tr[now<<1],tr[now<<1|1]); //cout<<tr[now].l1<<" "<<tr[now].l2<<" "<<tr[now].r1<<" "<<tr[now].r2<<endl;}void pointchange(int now,int l,int r,int pos){ if(l==r) { int x=q[l]; tr[now].d1=tr[now].d2=tr[now].d3=tr[now].d4=-inf; tr[now].l1=tr[now].l2=tr[now].r1=tr[now].r2=-inf; if (s[x][0]=='.') tr[now].d1=tr[now].l1=tr[now].r1=1; if (s[x][1]=='.') tr[now].d4=tr[now].l2=tr[now].r2=1; if (s[x][1]=='.'&&s[x][0]=='.') tr[now].d2=tr[now].d3=tr[now].l1=tr[now].l2=tr[now].r1=tr[now].r2=2; return; } int mid=(l+r)/2; if (pos<=mid) pointchange(now<<1,l,mid,pos); else pointchange(now<<1|1,mid+1,r,pos); tr[now]=update(tr[now<<1],tr[now<<1|1]); //cout<<tr[now].l1<<" "<<tr[now].l2<<" "<<tr[now].r1<<" "<<tr[now].r2<<endl;}data query(int now,int l,int r,int ll,int rr){ if (ll<=l&&r<=rr) return tr[now]; int mid=(l+r)/2; if (ll<=mid&&rr>mid) return update(query(now<<1,l,mid,ll,rr),query(now<<1|1,mid+1,r,ll,rr)); else if (ll<=mid) return query(now<<1,l,mid,ll,rr); else return query(now<<1|1,mid+1,r,ll,rr);}void clear(data &a){ a.d1=a.d2=a.d3=a.d4=0; a.l1=a.l2=a.r1=a.r2=0;}int solve(int x,int y){ if (s[x][0]=='#'&&s[x][1]=='#') return 0; data a,b; clear(a); clear(b); while (belong[x]!=belong[y]) { if (deep[belong[x]]>deep[belong[y]]) { a=update(query(1,1,n,pos[belong[x]],pos[x]),a); x=fa[belong[x]]; } else { b=update(query(1,1,n,pos[belong[y]],pos[y]),b); y=fa[belong[y]]; } } if (deep[x]<deep[y]) b=update(query(1,1,n,pos[x],pos[y]),b); else a=update(query(1,1,n,pos[y],pos[x]),a); swap(a.l1,a.r1); swap(a.l2,a.r2); swap(a.d2,a.d3); a=update(a,b); return max(a.l1,a.l2);}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); } dfs(1,0); dfs1(1,1); for (int i=1;i<=n;i++) scanf("%s",s[i]); build(1,1,n); //for (int i=1;i<=n;i++) cout<<pos[i]<<" "; cout<<endl; //for (int i=1;i<=n;i++) cout<<q[i]<<" "; cout<<endl; //cout<<tr[1].l1<<" "<<tr[1].l2<<" "<<tr[1].r1<<" "<<tr[1].r2<<endl; for (int i=1;i<=m;i++) { char opt[10]; int x,y; scanf("%s",opt); if (opt[0]=='Q') { scanf("%d%d",&x,&y); printf("%d\n",solve(x,y)); } else { scanf("%d",&x); scanf("%s",s[x]); pointchange(1,1,n,pos[x]); } }}
0 0
- bzoj 2325: [ZJOI2011]道馆之战 (树链剖分+线段树)
- 【BZOJ 2325】[ZJOI2011]道馆之战
- [BZOJ2325][ZJOI2011][树链剖分][线段树]道馆之战
- 【bzoj2325】【ZJOI2011】【道馆之战】【树链剖分】
- 【ZJOI2011】道馆之战
- bzoj2325 [ZJOI2011]道馆之战
- bzoj2325: [ZJOI2011]道馆之战
- bzoj 2229: [Zjoi2011]最小割 分治最小割(最小割树)
- BZOJ 2323: [ZJOI2011]细胞
- BZOJ 2819 Nim (树链剖分+线段树)
- BZOJ 2243 染色(树链剖分+线段树)
- bzoj 4127: Abs(树链剖分+线段树)
- bzoj 4127: Abs(树链剖分+线段树)
- BZOJ 2521: [Shoi2010]最小生成树&&2229: [Zjoi2011]最小割
- bzoj 2324 [ZJOI2011]营救皮卡丘(floyd,费用流)
- bzoj 1984(线段树+树链剖分)
- BZOJ 4034 树链剖分 + 线段树
- BZOJ 2836 树链剖分+线段树
- poj 2184 dp变种
- Eclipse中安装STS插件
- 258. Add Digits
- windows下安装TensorFlow
- Theano 中文文档 0.9 - 7.1.1 Python教程
- bzoj 2325: [ZJOI2011]道馆之战 (树链剖分+线段树)
- Android4大组件之ContentProvider跨项目访问数据Demo
- 【Android开发艺术探索读书笔记】 第一章 Activity的生命周期与启动模式
- wwwscan网站目录文件批量扫描工具
- angular2 父子组件的通信
- Theano 中文文档 0.9 - 7.1.2 NumPy新手
- Mac下常用工具
- 在Linux CentOS 6.6上安装Python 2.7.9
- 为什么说面向对象编程和函数式编程都有问题