BZOJ 1984: 月下“毛景树” [树链剖分 边权]

时间:2022-10-25 18:52:59

1984: 月下“毛景树”

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 1728  Solved: 531
[Submit][Status][Discuss]

Description

毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

Input

第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

Output

对于毛毛虫的每个询问操作,输出一个答案。

Sample Input

4
1 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop

Sample Output

9
16

【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。


比较明显树链剖分
问题边权怎么处理?
转化成边下面的点的权值就行了
 
因为修改操作是第几条边,所以保存mp点到边
 
线段树set修改标记,add增加标记
打set时清空add,打add时有set直接加set就行了
 
注意:不要直接用书上的点的编号的权值作为线段树编号的权值,加一个fid[i]为线段树节点i在原图上的编号!!!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define lc o<<1
#define rc o<<1|1
#define m ((l+r)>>1)
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
const int N=2e5+,INF=1e9+;
int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,u,v,ww,w[N],l,r,mp[N];//edge-->point
char s[];
struct edge{
int v,w,ne,id;
}e[N<<];
int h[N],cnt;
inline void ins(int u,int v,int w,int id){
cnt++;
e[cnt].v=v;e[cnt].w=w;e[cnt].id=id;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].w=w;e[cnt].id=id;e[cnt].ne=h[v];h[v]=cnt;
}
int tid[N],fa[N],top[N],tot,deep[N],mx[N],size[N],fid[N];
void dfs(int u){
size[u]=;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v==fa[u]) continue;
w[v]=e[i].w;mp[e[i].id]=v;
fa[v]=u;deep[v]=deep[u]+;
dfs(v);
size[u]+=size[v];
if(size[mx[u]]<size[v]) mx[u]=v;
}
}
void dfs(int u,int anc){
if(!u) return;
tid[u]=++tot;fid[tot]=u;
top[u]=anc;
dfs(mx[u],anc);
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
}
} struct node{
int mx,set,add;
node():set(-),add(){}
}t[N<<];
inline void merge(int o){
t[o].mx=max(t[lc].mx,t[rc].mx);
}
inline void paintset(int o,int v){
t[o].set=t[o].mx=v;
t[o].add=;
}
inline void paintadd(int o,int v){
if(t[o].set!=-) t[o].set+=v,t[o].mx+=v;
else t[o].add+=v,t[o].mx+=v;
}
inline void pushDown(int o){
if(t[o].set!=-){
paintset(lc,t[o].set);
paintset(rc,t[o].set);
t[o].set=-;
}
if(t[o].add){
paintadd(lc,t[o].add);
paintadd(rc,t[o].add);
t[o].add=;
}
}
void build(int o,int l,int r){
if(l==r) t[o].mx=w[fid[l]];
else{
build(lson);
build(rson);
merge(o);
}
}
void segcha(int o,int l,int r,int p,int v){
if(l==r) t[o].mx=v;
else{
pushDown(o);
if(p<=m) segcha(lson,p,v);
else segcha(rson,p,v);
merge(o);
}
}
void segcov(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr) paintset(o,v);
else{
pushDown(o);
if(ql<=m) segcov(lson,ql,qr,v);
if(m<qr) segcov(rson,ql,qr,v);
merge(o);
}
}
void segadd(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr) paintadd(o,v);
else{
pushDown(o);
if(ql<=m) segadd(lson,ql,qr,v);
if(m<qr) segadd(rson,ql,qr,v);
merge(o);
}
}
int segmx(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return t[o].mx;
else{
pushDown(o);
int mx=-INF;
if(ql<=m) mx=max(mx,segmx(lson,ql,qr));
if(m<qr) mx=max(mx,segmx(rson,ql,qr));
return mx;
}
} void add(int x,int y,int v){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
segadd(,,n,tid[top[x]],tid[x],v);
x=fa[top[x]];
} if(tid[x]>tid[y]) swap(x,y);
if(x!=y) segadd(,,n,tid[x]+,tid[y],v);//bian quan
}
void cover(int x,int y,int v){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
segcov(,,n,tid[top[x]],tid[x],v);
x=fa[top[x]];
} if(tid[x]>tid[y]) swap(x,y);
if(x!=y) segcov(,,n,tid[x]+,tid[y],v);//bian quan
}
int query(int x,int y){
int mx=-INF;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
mx=max(mx,segmx(,,n,tid[top[x]],tid[x]));
x=fa[top[x]];
}
if(tid[x]>tid[y]) swap(x,y);
if(x!=y) mx=max(mx,segmx(,,n,tid[x]+,tid[y]));
return mx;
}
int main(){
n=read();
for(int i=;i<=n-;i++) u=read(),v=read(),ww=read(),ins(u,v,ww,i);
dfs();dfs(,);
build(,,n);
while(true){
scanf("%s",s);
if(s[]=='S') break;
else if(s[]=='h') l=read(),v=read(),segcha(,,n,tid[mp[l]],v);
else if(s[]=='o') l=read(),r=read(),v=read(),cover(l,r,v);
else if(s[]=='d') l=read(),r=read(),v=read(),add(l,r,v);
else l=read(),r=read(),printf("%d\n",query(l,r));
}
}
 

BZOJ 1984: 月下“毛景树” [树链剖分 边权]的更多相关文章

  1. Bzoj 1984&colon; 月下&OpenCurlyDoubleQuote;毛景树” 树链剖分

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1282  Solved: 410[Submit][Status][Discu ...

  2. BZOJ 1984月下&OpenCurlyDoubleQuote;毛景树” LCT维护边权 &plus; 下传标记

    Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树” ...

  3. BZOJ 1984&colon; 月下&OpenCurlyDoubleQuote;毛景树” &lpar;树链剖分&plus;线段树&rpar;

    注意赋值和加法的标记下传优先级.具体看代码. CODE #include <vector> #include <queue> #include <cstdio> # ...

  4. BZOJ 1984 月下&OpenCurlyDoubleQuote;毛景树”

    我觉得我要把BZOJ上的链剖写完了吧.... #include<iostream> #include<cstdio> #include<cstring> #incl ...

  5. 【BZOJ】1984 月下&OpenCurlyDoubleQuote;毛景树”

    [算法]树链剖分+线段树 [题解]线段树的区间加值和区间覆盖操作不能同时存在,只能存在一个. 修改:从根节点跑到目标区域路上的标记全部下传,打完标记再上传回根节点(有变动才需要上传). 询问:访问到目 ...

  6. 【BZOJ-1984】月下&OpenCurlyDoubleQuote;毛景树” 树链剖分

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1314  Solved: 416[Submit][Status][Discu ...

  7. BZOJ1984&colon; 月下&OpenCurlyDoubleQuote;毛景树”

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 713  Solved: 245[Submit][Status] Descri ...

  8. 【BZOJ1984】月下&OpenCurlyDoubleQuote;毛景树” 树链剖分&plus;线段树

    [BZOJ1984]月下"毛景树" Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校 ...

  9. 树剖&plus;线段树&vert;&vert;树链剖分&vert;&vert;BZOJ1984&vert;&vert;Luogu4315&vert;&vert;月下&OpenCurlyDoubleQuote;毛景树”

    题面:月下“毛景树” 题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好).用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了:前三个更新的操作都可以合并起来,可以发现a到b节点间 ...

随机推荐

  1. ruby on rails 在centos 7下的安装配置

    因为想安装最新版本,所以通过编译安装. 安装前准备工具和库文件: sudo yum install gcc gcc-c++ openssl-devel readline-devel gdbm-deve ...

  2. ArrayList、HashTable、List、Dictionary的演化及如何选择使用

    在C#中,数组由于是固定长度的,所以常常不能满足我们开发的需求. 由于这种限制不方便,所以出现了ArrayList. ArrayList.List<T> ArrayList是可变长数组,你 ...

  3. Metaweblog在Android上使用

    同步发表于http://avenwu.net/2015/02/04/metaweblog metaweblog是一个博客接口协议,目前主流的博客平台均支持该协议,比如博客园,CSDN,WordPres ...

  4. homework07

    我阅读的: http://www.cnblogs.com/zhuyp1015/category/370450.html http://blog.csdn.net/hzyong_c/article/de ...

  5. windows的DOS窗口如何修改大小

    关于这个问题,其实很简单.不知道为什么网上的资料乱遭的.故自己写下来,方便有不明白的童鞋参考. 左键点击左上角的区域会弹出一个菜单,选择属性. 如下图就能轻松的修改窗口的大小了.

  6. 学习总结---BGP协议

    一.可以在自治域内使用BGP作为域内协议吗? 为什么?它和OSPF的关键差异是什么? 1.BGP的全称是边界网关协议,用于自治域间的路由传递,它不像OSPF协议,其重点不在于路由的计算,而在于路由的控 ...

  7. WebAssembly让你的Javascript计算性能提升70&percnt;

    现在的JavaScript代码要进行性能优化,通常使用一些常规手段,如:延迟执行.预处理.setTimeout等异步方式避免处理主线程,高大上一点的会使用WebWorker.即使对于WebWorker ...

  8. Kattis之旅——Factovisors

    The factorial function, n! is defined thus for n a non-negative integer: 0! = 1 n! = n * (n-1)! (n & ...

  9. tensorflow读取数据的方式

    转载:https://blog.csdn.net/u014038273/article/details/77989221 TensorFlow程序读取数据一共有四种方法(一般针对图像): 供给数据(F ...

  10. First Blood

    自我介绍 大家好!我的名字是戴俊涵,代号211606359,喜欢看电影和古风音乐,也是一个资深漫迷(让世界感受痛楚吧),喜欢的美食是牛排. 回想初衷 (1)回想一下你初入大学时对本专业的畅想 当初你是 ...