【bzoj4712】洪水

Portal --> bzoj4712

Description

  ?給你一棵樹,節點從\(1\)\(n\)編號,每個節點有一個權值,有若干次操作,操作有以下兩種:

\((C,x,delta)\):將編號為\(x\)的點的權值改為\(delta\)

\((Q,x)\):詢問將\(x\)號節點為根的子樹中的所有葉子結點與子樹外的其他所有葉子節點分離的最小代價,分離可以通過刪除節點實現,刪除一個節點的對應代價為該點的權值

  ?數據范圍:\(n<=200000\),任意\(delta\)均為非負數,答案在long long范圍內

Solution

  ?這題貌似是。。經典的動態dp問題,維護重鏈信息\(f\)和輕兒子信息之和\(g\)之后可以用樹剖解決

?  ?我們先考慮沒有修改操作的情況,那就是直接dp

?  ?記\(f[x]\)表示以\(x\)為根的子樹的答案,\(val[x]\)表示\(x\)點的權值,那么有:
\[ f[x]=min(val[x],\sum\limits_{x\rightarrow u}f[u]) \]
? 如果要修改的話我們考慮樹剖,再定義一個數組\(g\)\(g[x]\)表示\(x\)的輕兒子的\(f\)值之和,那么就有:
\[ f[x]=min(val[x],f[son[x]]+g[x]) \]
?  ?其中\(son[x]\)表示的是\(x\)的重兒子

?  ?這個時候就有好幾種不同的做法了,反正就是維護這兩個值就好了,接下來講的是一種通過維護一個類似轉移矩陣一樣的東西來用樹剖維護的方法

?  ?我們考慮定義一種新的矩陣乘法(額好像也不能叫做矩陣乘法反正就是一種新的運算):
\[ C[i][j]=min(A[i][k]+B[k][j]) \]
  ?其中\(A,B,C\)都是矩陣,其實這種運算就是將原來的矩陣乘法的乘法改成了取最小值

  ?這個運算是滿足結合律的,具體證明的話就是我們可以將一次這樣的運算理解成求最短路,然后連續兩次這樣的運算的話就是相當于你有三排點,要求最左邊到最右邊的最短路,顯然你可以先求出左邊兩排的最短路,或者先求出右邊兩排的最短路,最后得到的結果是一樣的

  ?定義完這樣的運算有什么用呢?我們可以考慮將\(f[x]\)的求值過程用這種運算來實現,為了方便表示我們將這種運算的符號約定為\(*\)
\[ \begin{bmatrix}f[x]\\0\end{bmatrix}=\begin{bmatrix}g[x]&val[x]\\0&0\end{bmatrix}*\begin{bmatrix}f[son[x]]\\0\end{bmatrix} \]
  ?具體的話就是。。大力展開一下就好了

?  ?然后我們可以發現\(\begin{bmatrix}f[son[x]]\\0\end{bmatrix}\)是可以寫成\(\begin{bmatrix}g[son[son[x]]]&val[son[son[x]]]\\0&0\end{bmatrix}\)的,一路寫下去就會發現其實就是\(x\)所在的整條重鏈中,從\(x\)這個位置的矩陣一路連續運算一直到重鏈底就好了

?  ?注意到這個剖完之后就是一段連續的區間,然后這樣我們就可以放心用線段樹來維護區間的矩陣的連續運算得到的結果,然后其他的就是跟樹剖差不多的操作了

?   ?

?  ?其實還是有(hen)點(da)區別的,具體一點就是

1、查詢

  ?與普通樹剖不同的是這樣我們維護的是。。某個位置到鏈底的權值運算和,所以。。我們需要記錄的是每個點所在的鏈底在哪里,然后查詢的時候并不需要往上跳直接查就好了

2、修改

  ?修改的話因為這里會影響到祖先的\(g\)值,所以我們還是要常規操作一路跳上去,不過不同的是,這里修改直接暴力通過線段樹區間查詢求得\(f[top[x]\)然后在\(g[pre[top[x]]]\)里面減去(\(pre[x]\)表示\(x\)在原樹上的直接祖先,\(top[x]\)表示\(x\)所在的重鏈頭),然后更新線段樹中的信息,然后再將新的值加回\(g[pre[top[x]]]\)

  ?

?  ?然后就十分愉悅\(O(nlog^2n)\)做完啦,這個做法有一個好處就是。。就算沒有保證修改的\(delta\)非負也可以直接做,以及重載運算符之后線段樹寫起來很爽qwq

?  ?以及洛谷上面貌似有碾爆LCT和樹剖的一個\(log\)做法qwq(orzlyy!!)然而。。我太懶了并沒有寫qwq

  ?

?  ?代碼大概長這個樣子

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=200010,SEG=N*4;
const ll inf=1LL<<60;
struct xxx{int y,nxt;
}a[N*2];
int h[N],lis[N],dfn[N],ed[N],pre[N],sz[N];//ed=the end of the chain
ll f[N],g[N],val[N];
int son[N],top[N];
int n,m,tot,dfn_t;
ll ans;
struct Mtrix{/*{{{*/ll a[2][2];int n;void init(int _n){n=_n;for (int i=0;i<n;++i)for (int j=0;j<n;++j) a[i][j]=inf;}friend Mtrix operator * (Mtrix x,Mtrix y){Mtrix ret; ret.n=x.n;for (int i=0;i<ret.n;++i)for (int j=0;j<ret.n;++j){ret.a[i][j]=inf;for (int k=0;k<ret.n;++k)if (x.a[i][k]!=inf&&y.a[k][j]!=inf)ret.a[i][j]=min(ret.a[i][j],x.a[i][k]+y.a[k][j]);}return ret;}
};/*}}}*/
namespace Seg{/*{{{*/int ch[SEG][2];Mtrix info[SEG];int n,tot;void pushup(int x){info[x]=info[ch[x][0]]*info[ch[x][1]];}void _build(int x,int l,int r){info[x].init(2);if (l==r){info[x].a[0][0]=g[lis[l]];info[x].a[0][1]=val[lis[l]];info[x].a[1][0]=info[x].a[1][1]=0;return;}int mid=l+r>>1;ch[x][0]=++tot; _build(ch[x][0],l,mid);ch[x][1]=++tot; _build(ch[x][1],mid+1,r);pushup(x);}void build(int _n){n=_n;tot=1;_build(1,1,n);}void _update(int x,int d,int lx,int rx){if (lx==rx){info[x].a[0][0]=g[lis[lx]];info[x].a[0][1]=val[lis[lx]];info[x].a[1][0]=info[x].a[1][1]=0;return;}int mid=lx+rx>>1;if (d<=mid) _update(ch[x][0],d,lx,mid);else _update(ch[x][1],d,mid+1,rx);pushup(x);}void update(int d){_update(1,d,1,n);}Mtrix _query(int x,int l,int r,int lx,int rx){if (l<=lx&&rx<=r) return info[x];int mid=lx+rx>>1;if (r<=mid) return _query(ch[x][0],l,r,lx,mid);else if (l>mid) return _query(ch[x][1],l,r,mid+1,rx);else{return _query(ch[x][0],l,mid,lx,mid)*_query(ch[x][1],mid+1,r,mid+1,rx);}}Mtrix query(int l,int r){return _query(1,l,r,1,n);}
}/*}}}*/
void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
void dfs(int fa,int x){int u;sz[x]=1; son[x]=0; pre[x]=fa;for (int i=h[x];i!=-1;i=a[i].nxt){u=a[i].y;if (u==fa) continue;dfs(x,u);sz[x]+=sz[u];if (sz[u]>sz[son[x]]) son[x]=u;}
}
void dfs1(int fa,int x){int u,cntson=0;dfn[x]=ed[x]=++dfn_t; lis[dfn_t]=x;if (son[x]){top[son[x]]=top[x];dfs1(x,son[x]);ed[x]=ed[son[x]];f[x]+=f[son[x]];++cntson;}for (int i=h[x];i!=-1;i=a[i].nxt){u=a[i].y;if (u==fa||u==son[x]) continue;top[u]=u;dfs1(x,u);g[x]+=f[u];++cntson;}if (cntson==0) g[x]=inf,f[x]=val[x];elsef[x]=min(val[x],f[x]+g[x]);
}
ll query(int x){Mtrix tmp=Seg::query(dfn[x],ed[x]);return min(tmp.a[0][0],tmp.a[0][1]);
}
void update(int x,int delta){ll tmp;val[x]+=delta;while (top[x]){tmp=query(top[x]);if (pre[top[x]])g[pre[top[x]]]-=tmp;Seg::update(dfn[x]);tmp=query(top[x]);if (pre[top[x]])g[pre[top[x]]]+=tmp;x=pre[top[x]];}
}int main(){
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);
#endifchar op[5];int x,y;scanf("%d",&n);for (int i=1;i<=n;++i) scanf("%lld",val+i);memset(h,-1,sizeof(h));tot=0;for (int i=1;i<n;++i){scanf("%d%d",&x,&y);add(x,y); add(y,x);}dfs(0,1);top[1]=1; dfn_t=0;dfs1(0,1);Seg::build(dfn_t);scanf("%d",&m);for (int i=1;i<=m;++i){scanf("%s",&op);if (op[0]=='C'){scanf("%d%d",&x,&y);update(x,y);}else{scanf("%d",&x);ans=query(x);printf("%lld\n",ans);}}
}

轉載于:https://www.cnblogs.com/yoyoball/p/9513666.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249664.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249664.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249664.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[USACO]地震 (二分答案+最優比率生成樹詳解)

題面&#xff1a;[USACO 2001 OPEN]地震 題目描述&#xff1a; 一場地震把約翰家的牧場摧毀了&#xff0c; 堅強的約翰決心重建家園。 約翰已經重建了N個牧場&#xff0c;現在他希望能修建一些道路把它們連接起來。研究地形之后&#xff0c;約翰發現可供修建的道路有M條。碰巧的…

HTTP協議學習筆記

1.HTTP協議簡介 &#xff08;1&#xff09;客戶端連上web服務器后&#xff0c;若想獲得web服務器中的某個web資源&#xff0c;需遵守一定的通訊格式&#xff0c;HTTP協議用于定義客戶端與web服務器通迅的格式。 &#xff08;2&#xff09;HTTP是hypertext transfer protocol&…

defer和async的原理與區別

上一篇剛轉載了一篇有關于網站性能優化的文章&#xff0c;其中提及到了頁面的加載和渲染的過程&#xff0c;提到了defer和async的相關區別&#xff0c;但是本人在此之前并沒有深究其中的區別。 defer和async是script標簽的兩個屬性&#xff0c;用于在不阻塞頁面文檔解析的前提…

一些奇妙的線段樹操作

學過數據結構和會做題完全是兩個概念orz 各種各樣的題目都應該見識一下 簡單的目錄&#xff1a; 最大連續長度 吉司機線段樹 線段樹合并/分裂 最大連續長度問題 典型題目&#xff1a;HDU 3911 &#xff08;$Black$ $And$ $White$&#xff09; 題目大意&#xff1a;有一個長度為…

微服務實踐沙龍-上海站

微服務的概念最早由Martin Fowler與James Lewis于2014年共同提出&#xff0c;核心思想是圍繞業務能力組織服務&#xff0c;各個微服務可被獨立部署&#xff0c;服務間是松耦合的關系&#xff0c;以及數據和治理的去中心化管理。微服務能夠幫助企業應對業務復雜、頻繁更新以及團…

Spring的refresh()方法調用過程

Spring的refresh()方法調用過程 refresh()是Spring中比較核心的方法&#xff0c;Spring所有的初始化都在這個方法中完成 具體代碼如下 public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this co…

Web數據存儲之localStorage和sessionStorage

Web數據存儲之localStorage和sessionStorage 學習前端以來&#xff0c;自己了解有localStorage和sessionStorage的相關存儲的知識&#xff0c;也有實踐過&#xff0c;但是之前只限于能用的基礎上&#xff0c;但最近看了一本書&#xff0c;深入了解了localStorage和sessionStor…

(四)RabbitMQ消息隊列-服務詳細配置與日常監控管理

&#xff08;四&#xff09;RabbitMQ消息隊列-服務詳細配置與日常監控管理 原文:&#xff08;四&#xff09;RabbitMQ消息隊列-服務詳細配置與日常監控管理RabbitMQ服務管理 啟動服務&#xff1a;rabbitmq-server -detached【 /usr/local/rabbitmq/sbin/rabbitmq-server -deta…

oracle中delete、truncate、drop的區別 (轉載)

一、delete 1、delete是DML&#xff0c;執行delete操作時&#xff0c;每次從表中刪除一行&#xff0c;并且同時將該行的的刪除操作記錄在redo和undo表空間中以便進行回滾&#xff08;rollback&#xff09;和重做操作&#xff0c;但要注意表空間要足夠大&#xff0c;需要手動提交…

前端開發工程化探討--基礎篇(長文)

轉載自UC資深前端工程師張云龍的github 喂喂喂&#xff0c;那個切圖的&#xff0c;把頁面寫好就發給研發工程師套模板吧。 你好&#xff0c;切圖仔。 不知道你的團隊如何定義前端開發&#xff0c;據我所知&#xff0c;時至今日仍然有很多團隊會把前端開發歸類為產品或者設計崗…

Python讀取Json字典寫入Excel表格的方法

需求&#xff1a; 因需要將一json文件中大量的信息填入一固定格式的Excel表格&#xff0c;單純的復制粘貼肯定也能完成&#xff0c;但是想偷懶一下&#xff0c;于是借助Python解決問題。 環境&#xff1a; Windows7 Python2.7 Xlwt 具體分析&#xff1a; 原始文件為json列表&am…

Spring-BeanFactory源碼分析

正式進入Spring 源碼分析這個模塊了&#xff0c;對于spring這個龐大的工程&#xff0c;如果要一點點的完全分析是非常困難的&#xff0c;對于應用型框架&#xff0c;我還是偏向于掌握思想或者設計&#xff0c;而不是記住代碼&#xff0c;對于初次看spring源碼&#xff0c;相信大…

Linux查看修改時間、時區

同步網絡時間 yum install ntpntpdate time.nist.gov timedatectl set-timezone Asia/Shanghai如果上面time.nist.gov服務器同步不了&#xff0c;可以換下面幾個時間服務器試試&#xff1a;time.nist.govtime.nuri.net0.asia.pool.ntp.org1.asia.pool.ntp.org2.asia.pool.ntp.o…

我所知道的HTTP和HTTPS

摘要&#xff1a;相比之前的傳輸協議&#xff0c;HTTP/2在底層方面做了很多優化。有安全、省時、簡化開發、更好的適應復雜頁面、提供緩存利用率等優勢&#xff0c;阿里云早在去年發布的CDN6.0服務就已正式支持HTTP/2&#xff0c;訪問速度最高可提升68%。 寫在前面 超文本傳輸…

sql server常用性能計數器

https://blog.csdn.net/kk185800961/article/details/52462913?utm_sourceblogxgwz5 https://blog.csdn.net/kk185800961/article/details/27657239 以下部分轉自&#xff1a;http://www.cnblogs.com/zhijianliutang/p/4174697.html 常規計數器 收集操作系統服務器的服務器性能…

Python中正反斜杠('/'和'\')的意義

剛剛在學習些測試報告的時候&#xff0c;出現一個路徑的問題&#xff0c;找了很久的原因&#xff0c;竟然是少了一個反斜杠引起的&#xff0c;在此順便記錄一下正反斜杠的作用。 在Python中&#xff0c;記錄路徑時有以下幾種寫法&#xff0c;如&#xff1a;&#xff08;大家都知…

什么是IOC容器

1.IOC不是一種技術&#xff0c;只是一種思想&#xff0c;一個重要的面向對象編程的法則&#xff0c;它能指導我們如何設計出松耦合&#xff0c;更優良的程序。傳統應用程序都是由我們在類內部主動創建依賴對象&#xff0c;從而導致類與類之間高耦合&#xff0c;難于測試&#x…

Jenkins配置與使用

Jenkins是一個開源軟件項目&#xff0c;旨在提供一個開放易用的軟件平臺&#xff0c;使軟件的持續集成變成可能。Jenkins是基于Java開發的一種持續集成工具&#xff0c;用于監控持續重復的工作&#xff0c;功能包括&#xff1a;1、持續的軟件版本發布/測試項目。2、監控外部調用…

fastDFS使用

fastDFS : 分布式文件系統C語言開發,fastDFS為互聯網量身定制,考慮到了冗余備份,負載均衡,線性擴容...很容易搭建集群文件存儲系統.存儲在fastDFS圖片:相當于存儲在本地磁盤一樣訪問圖片:相當于訪問本地磁盤存儲結構:組名/虛擬磁盤路徑/動態生成文件名.擴展名192.168.100.20/gr…