日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[树链剖分]List wants to travel,Relief grain,hotel加强版,This world need more Zhu

發(fā)布時(shí)間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [树链剖分]List wants to travel,Relief grain,hotel加强版,This world need more Zhu 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • B:Relief grain
  • C:hotel加強(qiáng)版

B:Relief grain

題目

將一段區(qū)間修改的標(biāo)記變成差分,每次都是連續(xù)一段的dfndfndfn序修改

從小到大枚舉dfndfndfn,在一段標(biāo)記的最開頭的dfndfndfn插入,最末尾的dfndfndfn+1+1+1刪除

就保證了在這連續(xù)的一段都出現(xiàn)了

此時(shí)仍然存在于線段樹中的標(biāo)記就一定是經(jīng)過dfndfndfn序?qū)?yīng)回原樹的節(jié)點(diǎn)

#include <cstdio> #include <vector> #include <cstring> #include <iostream> using namespace std; #define maxn 100005 #define MAX 100000 vector < int > G[maxn], ins[maxn], del[maxn]; int n, m, cnt; int siz[maxn], son[maxn], f[maxn], dep[maxn]; int dfn[maxn], top[maxn], rnk[maxn]; int t[maxn << 2], id[maxn << 2], ans[maxn];void dfs1( int u, int fa ) {son[u] = 0, siz[u] = 1, dep[u] = dep[fa] + 1, f[u] = fa;for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == fa ) continue;dfs1( v, u );siz[u] += siz[v];if( ! son[u] || siz[v] > siz[son[u]] )son[u] = v;} }void dfs2( int u, int t ) {top[u] = t, dfn[u] = ++ cnt, rnk[cnt] = u;if( ! son[u] ) return;dfs2( son[u], t );for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == f[u] || v == son[u] ) continue;else dfs2( v, v );} }void pushup( int num ) {if( t[num << 1] >= t[num << 1 | 1] ) t[num] = t[num << 1], id[num] = id[num << 1];else t[num] = t[num << 1 | 1], id[num] = id[num << 1 | 1]; }void build( int num, int l, int r ) {t[num] = id[num] = 0;if( l == r ) {id[num] = l;return;}int mid = ( l + r ) >> 1;build( num << 1, l, mid );build( num << 1 | 1, mid + 1, r ); }void modify( int num, int l, int r, int pos, int v ) {if( l == r ) {t[num] += v;return;}int mid = ( l + r ) >> 1;if( pos <= mid ) modify( num << 1, l, mid, pos, v );else modify( num << 1 | 1, mid + 1, r, pos, v );pushup( num ); }void solve( int u, int v, int w ) {int fu = top[u], fv = top[v];while( fu != fv ) {if( dep[fu] < dep[fv] ) swap( fu, fv ), swap( u, v );ins[dfn[fu]].push_back( w );del[dfn[u] + 1].push_back( w );u = f[fu], fu = top[u];}if( dep[u] < dep[v] ) swap( u, v );ins[dfn[v]].push_back( w );del[dfn[u] + 1].push_back( w ); }int main() {while( ~ scanf( "%d %d", &n, &m ) ) {if( ! n && ! m ) return 0;for( int i = 1;i <= n;i ++ ) G[i].clear(), ins[i].clear(), del[i].clear();cnt = 0;for( int i = 1, u, v;i < n;i ++ ) {scanf( "%d %d", &u, &v );G[u].push_back( v );G[v].push_back( u );}dfs1( 1, 0 );dfs2( 1, 1 );for( int i = 1, x, y, z;i <= m;i ++ ) {scanf( "%d %d %d", &x, &y, &z );solve( x, y, z );}build( 1, 1, MAX );for( int i = 1;i <= n;i ++ ) {for( int j = 0;j < ins[i].size();j ++ )modify( 1, 1, MAX, ins[i][j], 1 );for( int j = 0;j < del[i].size();j ++ )modify( 1, 1, MAX, del[i][j], -1 );if( t[1] ) ans[rnk[i]] = id[1];else ans[rnk[i]] = 0;}for( int i = 1;i <= n;i ++ )printf( "%d\n", ans[i] );}return 0; }

C:hotel加強(qiáng)版

鏈接

f[u][j]f[u][j]f[u][j]表示uuu子樹內(nèi)距離uuujjj的點(diǎn)個(gè)數(shù)

g[u][j]g[u][j]g[u][j]表示uuu子樹內(nèi)存在兩個(gè)點(diǎn)距離它們的lcalcalcaddd,且lcalcalca距離uuud?jd-jd?j

樹形DPDPDP,是一個(gè)一個(gè)兒子暴力計(jì)算貢獻(xiàn)的

ans+=f[u][j]×g[v][j+1]+g[u][j]×f[v][j?1]ans+=f[u][j]\times g[v][j+1]+g[u][j]\times f[v][j-1]ans+=f[u][j]×g[v][j+1]+g[u][j]×f[v][j?1]

f[u][j]×g[v][j+1]f[u][j]\times g[v][j+1]f[u][j]×g[v][j+1]:在uuu已處理過的兒子中距離uuujjj,那么距離現(xiàn)在處理的兒子vvv的距離則為j+1j+1j+1,所以是和以vvv為根的子樹內(nèi)的距離j+1j+1j+1點(diǎn)對進(jìn)行匹配,即g[v][j+1]g[v][j+1]g[v][j+1]

g[u][j]×f[v][j?1]g[u][j]\times f[v][j-1]g[u][j]×f[v][j?1]:在uuu已處理過的兒子中,兩點(diǎn)距離lcalcalcadddlcalcalca距離uuud?jd-jd?j的點(diǎn)對數(shù)為g[u][j]g[u][j]g[u][j],能與現(xiàn)在處理的兒子vvv匹配的點(diǎn)個(gè)數(shù)則為f[v][j?1]f[v][j-1]f[v][j?1]f[v][j?1]f[v][j-1]f[v][j?1]的點(diǎn)距離vvvj?1j-1j?1,距離uuu就是jjj

g[u][j+1]+=f[u][j+1]×f[v][j]g[u][j+1]+=f[u][j+1]\times f[v][j]g[u][j+1]+=f[u][j+1]×f[v][j]f[u][j+1],f[v][j]f[u][j+1],f[v][j]f[u][j+1],f[v][j]相互匹配的點(diǎn)對是很特殊的,因?yàn)檫@些點(diǎn)對的lcalcalca就是uuu,這些點(diǎn)對距離lcalcalcaj+1j+1j+1lcalcalca距離uuu的距離為(j+1)?(j+1)=0(j+1)-(j+1)=0(j+1)?(j+1)=0,是符合ggg的定義的

這種特殊的情況統(tǒng)計(jì)后,在uuu往上跳的過程中,uuu不斷降級為兒子,目前特殊的lcalcalca等于根的情況在以后就變成了下邊的一般化的ggg的轉(zhuǎn)移,那個(gè)時(shí)候uuu對根的貢獻(xiàn)就是正確的了,類似于局部最優(yōu)的這種思想,特殊情況往上跳就變成了一般情況

g[u][j?1]+=g[v][j]g[u][j-1]+=g[v][j]g[u][j?1]+=g[v][j]

g[u][j?1]+=g[v][j]g[u][j-1]+=g[v][j]g[u][j?1]+=g[v][j]g[v][j]g[v][j]g[v][j]vvv子樹內(nèi)lcalcalca距離vvvd?jd-jd?j的點(diǎn)對數(shù),這些點(diǎn)對數(shù)的lcalcalca距離uuu則為d?j+1d-j+1d?j+1


f[u][j+1]+=f[v][j]f[u][j+1]+=f[v][j]f[u][j+1]+=f[v][j]

f[u][j+1]+=f[v][j]f[u][j+1]+=f[v][j]f[u][j+1]+=f[v][j]:很好理解,距離uuuj+1j+1j+1的點(diǎn)個(gè)數(shù)加上距離當(dāng)前正在處理的兒子vvv距離為jjj(距離uuu就為j+1j+1j+1)的個(gè)數(shù)

長鏈剖分即可

長鏈剖分不同于重鏈剖分的無非是不再選用子樹最大的兒子作為重兒子,而是選用長度最長(葉子節(jié)點(diǎn)深度最深)的兒子作為重兒子

用于處理只與深度有關(guān)的樹上問題

#include <cstdio> #include <vector> #include <iostream> using namespace std; #define maxn 100005 #define int long long vector < int > G[maxn]; int n; int dep[maxn], son[maxn]; int *f[maxn], *g[maxn], tmp[maxn << 2], *ip = tmp, ans;void dfs1( int u, int fa ) {for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == fa ) continue;dfs1( v, u );dep[u] = max( dep[u], dep[v] );if( dep[v] > dep[son[u]] ) son[u] = v;}dep[u] = dep[son[u]] + 1; }void dfs2( int u, int fa ) {if( son[u] ) {f[son[u]] = f[u] + 1;g[son[u]] = g[u] - 1;dfs2( son[u], u );}f[u][0] = 1; ans += g[u][0];for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == son[u] || v == fa ) continue;f[v] = ip, ip += ( dep[v] << 1 );g[v] = ip, ip += ( dep[v] << 1 );dfs2( v, u );for( int j = 0;j <= dep[v];j ++ ) {ans += f[u][j] * g[v][j + 1];if( j ) ans += g[u][j] * f[v][j - 1];}for( int j = 0;j <= dep[v];j ++ ) {if( j ) g[u][j - 1] += g[v][j];g[u][j + 1] += f[u][j + 1] * f[v][j];f[u][j + 1] += f[v][j];}} }signed main() {scanf( "%lld", &n );for( int i = 1, u, v;i < n;i ++ ) {scanf( "%lld %lld", &u, &v );G[u].push_back( v );G[v].push_back( u ); }dfs1( 1, 0 );f[1] = ip, ip += ( dep[1] << 1 );g[1] = ip, ip += ( dep[1] << 1 );dfs2( 1, 0 );printf( "%lld\n", ans );return 0; }

總結(jié)

以上是生活随笔為你收集整理的[树链剖分]List wants to travel,Relief grain,hotel加强版,This world need more Zhu的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。