【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”
裸题,但是因为权在边上,所以要先把边权放到这条边的子节点上,然后进行链更新/查询的时候不能更新/查询其lca。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 100001
#define BN 320
#define INF 2147483647
int fa[N],dep[N],siz[N],son[N],Num[N],tot,top[N],a[N],bw[N],n,A[N],B[N],bs[N];
int en,first[N],next[N<<1],v[N<<1],sz,NOT;
void AddEdge(const int &U,const int &V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
void dfs(int U,int Fa,int d)
{
fa[U]=Fa;
dep[U]=d;
siz[U]=1;
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U])
{
dfs(v[i],U,d+1);
siz[U]+=siz[v[i]];
if(siz[v[i]]>siz[son[U]])
son[U]=v[i];
}
}
void dfs2(int U)
{
if(son[U])
{
top[son[U]]=top[U];
Num[son[U]]=++tot;
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];
Num[v[i]]=++tot;
dfs2(v[i]);
}
}
int SIZ[N],TOP[N];
void dfs3(int U)
{
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U])
{
if(SIZ[TOP[U]]<sz)
{
TOP[v[i]]=TOP[U];
++SIZ[TOP[U]];
}
dfs3(v[i]);
}
}
int lca(int U,int V)
{
while(U!=V)
{
if(TOP[U]!=TOP[V])
{
if(dep[TOP[U]]<dep[TOP[V]])
swap(U,V);
U=fa[TOP[U]];
}
else
{
if(dep[U]<dep[V])
swap(U,V);
U=fa[U];
}
}
return U;
}
int sum=1,num[N],l[BN],r[BN],maxv[BN],cov[BN],add[BN];
void makeblock()
{
for(;sum*sz<n;++sum)
{
l[sum]=r[sum-1]+1;
r[sum]=sum*sz;
maxv[sum]=-INF;
cov[sum]=INF;
for(int i=l[sum];i<=r[sum];++i)
{
num[i]=sum;
maxv[sum]=max(maxv[sum],a[i]);
}
}
l[sum]=r[sum-1]+1;
r[sum]=n;
maxv[sum]=-INF;
cov[sum]=INF;
for(int i=l[sum];i<=r[sum];++i)
{
num[i]=sum;
maxv[sum]=max(maxv[sum],a[i]);
}
}
void work_cov(const int &x,const int &y,const int &v)
{
for(int i=x;i<=y;++i)
a[i]=v;
}
void work_add(const int &x,const int &y,const int &v)
{
for(int i=x;i<=y;++i)
a[i]+=v;
}
void pushdown(const int &bl)
{
if(cov[bl]!=INF)
{
work_cov(l[bl],r[bl],cov[bl]);
cov[bl]=INF;
}
if(add[bl])
{
work_add(l[bl],r[bl],add[bl]);
add[bl]=0;
}
}
void calc(const int &bl)
{
maxv[bl]=-INF;
for(int i=l[bl];i<=r[bl];++i)
maxv[bl]=max(maxv[bl],a[i]);
}
void Update0(const int &x,const int &y)
{
int pl=Num[bs[x]];
pushdown(num[pl]);
a[pl]=y;
calc(num[pl]);
}
void Cov(const int &x,const int &y,const int &v)
{
pushdown(num[x]);
pushdown(num[y]);
if(num[x]==num[y])
{
work_cov(x,y,v);
calc(num[x]);
}
else
{
work_cov(x,r[num[x]],v);
calc(num[x]);
work_cov(l[num[y]],y,v);
calc(num[y]);
for(int i=num[x]+1;i<num[y];++i)
{
add[i]=0;
cov[i]=maxv[i]=v;
}
}
}
void Add(const int &x,const int &y,const int &v)
{
pushdown(num[x]);
pushdown(num[y]);
if(num[x]==num[y])
{
work_add(x,y,v);
calc(num[x]);
}
else
{
work_add(x,r[num[x]],v);
calc(num[x]);
work_add(l[num[y]],y,v);
calc(num[y]);
for(int i=num[x]+1;i<num[y];++i)
{
add[i]+=v;
maxv[i]+=v;
}
}
}
int Query(const int &x,const int &y)
{
int res=-INF;
pushdown(num[x]);
pushdown(num[y]);
if(num[x]==num[y])
for(int i=x;i<=y;++i)
res=max(res,a[i]);
else
{
for(int i=x;i<=r[num[x]];++i)
res=max(res,a[i]);
for(int i=l[num[y]];i<=y;++i)
res=max(res,a[i]);
for(int i=num[x]+1;i<num[y];++i)
res=max(res,maxv[i]);
}
return res;
}
void Change_cov(const int &L,const int &R,const int &W)
{
if(L==R&&Num[NOT]==L) return;
if(Num[NOT]==L) Cov(L+1,R,W);
else if(Num[NOT]==R) Cov(L,R-1,W);
else if(Num[NOT]>L&&Num[NOT]<R)
{
Cov(L,Num[NOT]-1,W);
Cov(Num[NOT]+1,R,W);
}
else Cov(L,R,W);
}
void Update_cov(int U,int V,const int &W)
{
int f1=top[U],f2=top[V];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(U,V);
swap(f1,f2);
}
Change_cov(Num[f1],Num[U],W);
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
Change_cov(Num[U],Num[V],W);
}
void Change_add(const int &L,const int &R,const int &W)
{
if(L==R&&Num[NOT]==L) return;
if(Num[NOT]==L) Add(L+1,R,W);
else if(Num[NOT]==R) Add(L,R-1,W);
else if(Num[NOT]>L&&Num[NOT]<R)
{
Add(L,Num[NOT]-1,W);
Add(Num[NOT]+1,R,W);
}
else Add(L,R,W);
}
void Update_add(int U,int V,const int &W)
{
int f1=top[U],f2=top[V];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(U,V);
swap(f1,f2);
}
Change_add(Num[f1],Num[U],W);
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
Change_add(Num[U],Num[V],W);
}
int Talk(const int &L,const int &R)
{
if(L==R&&Num[NOT]==L) return (-INF);
if(Num[NOT]==L) return Query(L+1,R);
if(Num[NOT]==R) return Query(L,R-1);
if(Num[NOT]>L&&Num[NOT]<R) return max(Query(L,Num[NOT]-1),Query(Num[NOT]+1,R));
return Query(L,R);
}
int Query_max(int U,int V)
{
int f1=top[U],f2=top[V],res=-INF;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(U,V);
swap(f1,f2);
}
res=max(res,Talk(Num[f1],Num[U]));
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
return max(res,Talk(Num[U],Num[V]));
}
//int cnt,LL[N],RR[N];
//void dfs4(int U)
//{
// LL[U]=++cnt;
// for(int i=first[U];i;i=next[i])
// if(v[i]!=fa[U])
// dfs4(v[i]);
// RR[U]=cnt;
//}
//int Init(const int &x,const int &y)
//{
// if(y>=LL[x]&&y<=RR[x]) return x;
// if(x>=LL[y]&&x<=RR[y]) return y;
// return lca(x,y);
//}
int main()
{
// freopen("bzoj1984.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<n;++i)
{
scanf("%d%d%d",&A[i],&B[i],&bw[i]);
AddEdge(A[i],B[i]);
AddEdge(B[i],A[i]);
}
top[1]=1;
Num[1]=++tot;
dfs(1,0,1);
dfs2(1);
sz=sqrt(n); if(!sz) sz=1;
for(int i=1;i<=n;i++)
{
SIZ[i]=1;
TOP[i]=i;
}
dfs3(1);
for(int i=1;i<n;++i)
{
if(fa[A[i]]==B[i])
bs[i]=A[i];
else
bs[i]=B[i];
a[Num[bs[i]]]=bw[i];
}
a[Num[1]]=-INF;
makeblock();
// dfs4(1);
char op[7];
int x,y,z;
while(1)
{
scanf("%s",op);
if(op[0]=='S') break;
scanf("%d%d",&x,&y);
if(op[0]=='C'&&op[1]=='h') Update0(x,y);
else if(op[0]=='C'&&op[1]=='o')
{
NOT=lca(x,y);
scanf("%d",&z);
Update_cov(x,y,z);
}
else if(op[0]=='A')
{
NOT=lca(x,y);
scanf("%d",&z);
Update_add(x,y,z);
}
else
{
NOT=lca(x,y);
printf("%d\n",Query_max(x,y));
}
}
return 0;
}
【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”的更多相关文章
- BZOJ1984: 月下“毛景树”
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 713 Solved: 245[Submit][Status] Descri ...
- [BZOJ1984]月下“毛景树”解题报告|树链剖分
Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树” ...
- [bzoj1984]月下“毛景树”
Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园.毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的" ...
- 2018.10.27 bzoj1984: 月下“毛景树”(树链剖分)
传送门 唉蒟蒻又退化了,这道sb题居然做了20min,最后发现是updcovupdcovupdcov写成了updaddupdaddupdadd我还能说什么233233233 就是让你转边权为点权之后, ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- 【BZOJ-1984】月下“毛景树” 树链剖分
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1314 Solved: 416[Submit][Status][Discu ...
- Bzoj 1984: 月下“毛景树” 树链剖分
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1282 Solved: 410[Submit][Status][Discu ...
- P4315 月下“毛景树”(树链剖分)
P4315 月下"毛景树"(树链剖分) 题面 简述: 边权转点权(在dfs1处转换) 把一条边权赋值在深度更深的上 需要实现对单边权的染色 , 路径边权的染色 , 路径边权的增加 ...
- 【BZOJ1984】月下“毛景树” 树链剖分+线段树
[BZOJ1984]月下"毛景树" Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校 ...
随机推荐
- noip 2011观光公交
P1315 观光公交 95通过 244提交 题目提供者该用户不存在 标签贪心递推2011NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录 题目描述 风景迷人的小城Y 市,拥有n 个美 ...
- Bash 实例,第二部分
我们先看一下处理命令行自变量的简单技巧,然后再看看 bash 基本编程结构. 接收自变量 在 介绍性文章 中的样本程序中,我们使用环境变量 "$1" 来引用第一个命令行自变量.类似 ...
- jquery学习之事件委派
一.定义 事件委派的定义就是,把原来加给子元素身上的事件绑定在父元素身上,就是把事件委派给父元素. 二.版本 从jQuery1.7开始,jQuery引入了全新的事件绑定机制,on()和off()两个函 ...
- session超时设置+超时页面跳转
session超时设置,方法有三种: (1)在主页面或者公共页面中加入:session.setMaxInactiveInterval(600);参数600单位是秒,即在没有10分钟活动后,sessio ...
- ${pageContext.request.contextPath}的解释以及和request.contextPath的区别
JSP中究竟采用绝对路径还是采用相对路径随着所采用技术的越来越复杂,这个问题也变得越来越难以解决. 1)采用相对路径遇到的问题 l 相对路径固然比较灵活,但如果想复制页面内的代码却变得比较困难,因为不 ...
- 动态规划:LCS
先上状态转移方程,还是很容易看明白的 例题是Codevs的1862,这个题不是实现了方程就可以了的,还要完成一个事情那就是计数,数一数到底有多少个最长公共子序列 #include<cstdio& ...
- JSP页面中格式化日期为指顶格式
有时候在页面中显示直接从数据库获取的日期时候会出现英文的日期格式.比如:
- 多表查询与pymysql
一.子查询 #1:子查询是将一个查询语句嵌套在另一个查询语句中. #2:内层查询语句的查询结果,可以为外层查询语句提供查询条件. #3:子查询中可以包含:IN.NOT IN.ANY.ALL.EXIST ...
- 无线路由器中WMM/Short GI/AP隔离各是什么功能, 开启时PC无法ping通手机.
无线路由器的WMM功能和开启ap隔离,以及开启ShortGI有什么用 无线路由器中有开启WMM.开启Short GI和开启AP隔离分别代表什么呢?这是我在我的TP-LINK无线路由器TL-WR84 ...
- linux设备驱动中的并发控制【转】
转自:http://www.cnblogs.com/plinx/archive/2013/01/28/2873121.html 在linux内核中,主要的静态发生于以下几种情况: 1.对称多处理器(S ...