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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[NOI2021 day1]轻重边(树链剖分),路径交点(矩阵行列式)

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [NOI2021 day1]轻重边(树链剖分),路径交点(矩阵行列式) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

NOI 2021 day1

  • 輕重邊
    • description
    • solution
    • code
  • 路徑交點
    • description
    • solution
    • code

輕重邊

description

solution

  • case=1~6

    把父親和兒子的邊轉化為儲存在兒子上的點

    建樹,暴力爬lcalcalca,暴力修改,O(n2)O(n^2)O(n2)

  • case=A

    對于一條鏈的情況,每次修改重邊就是一段區間,輕邊只有兩個端點相連的邊

    同樣的邊化點,線性用線段樹區間/單點修改,區間查詢

  • case=B

    第二類操作詢問只有一條邊,考慮這條邊怎么才可能是重邊,顯然就是兩個點最后被經過的時間戳要一樣

    樹鏈剖分打時間戳

  • case=1~20

    正解其實就在case=B基礎上,的確一條邊如果是輕邊當且僅當該邊的兩個端點所打時間戳不同

    樹鏈剖分維護數顏色段的個數(輕邊的數量),重邊數量減一下就可以了

    最原始局面全都是輕邊,所以初始化建樹時就要給每個點打一個不同的時間戳

蒟蒻只想到所有到case=B的前70%70\%70%的部分分,實在沒想到顏色段個數

code

#include <cstdio> #include <vector> #include <iostream> using namespace std; #define maxn 100005 #define lson num << 1 #define rson num << 1 | 1 struct node {int cnt, l, r, tag; }t[maxn << 2]; vector < int > G[maxn]; int T, n, m, cnt; int dep[maxn], son[maxn], top[maxn], dfn[maxn], f[maxn], siz[maxn];void dfs1( int u, int fa ) {dep[u] = dep[fa] + 1, f[u] = fa, siz[u] = 1;for( auto v : G[u] ) {if( v == fa ) continue;else dfs1( v, u );siz[u] += siz[v];if( siz[v] > siz[son[u]] )son[u] = v; } }void dfs2( int u, int tt ) {top[u] = tt, dfn[u] = ++ cnt;if( son[u] ) dfs2( son[u], tt );else return;for( auto v : G[u] ) {if( v == f[u] || v == son[u] ) continue;else dfs2( v, v );} }void pushdown( int num ) {if( ! t[num].tag ) return;t[lson].l = t[lson].r = t[lson].tag = t[num].tag;t[rson].l = t[rson].r = t[rson].tag = t[num].tag;t[lson].cnt = t[rson].cnt = 1;t[num].tag = 0;return; }void build( int num, int l, int r ) {if( l == r ) {t[num].cnt = 1, t[num].l = t[num].r = l;return;}int mid = ( l + r ) >> 1;build( lson, l, mid );build( rson, mid + 1, r );t[num].l = t[lson].l, t[num].r = t[rson].r;t[num].cnt = t[lson].cnt + t[rson].cnt;t[num].tag = 0; }void modify( int num, int l, int r, int L, int R, int id ) {if( R < l || r < L ) return;if( L <= l && r <= R ) {t[num].cnt = 1, t[num].l = t[num].r = t[num].tag = id;return;}pushdown( num );int mid = ( l + r ) >> 1;modify( lson, l, mid, L, R, id );modify( rson, mid + 1, r, L, R, id );t[num].l = t[lson].l, t[num].r = t[rson].r;t[num].cnt = t[lson].cnt + t[rson].cnt - ( t[lson].r == t[rson].l ); }void modify( int x, int y, int id ) {while( top[x] ^ top[y] ) {if( dep[top[x]] < dep[top[y]] ) swap( x, y );modify( 1, 1, n, dfn[top[x]], dfn[x], id );x = f[top[x]];}if( dep[x] > dep[y] ) swap( x, y );modify( 1, 1, n, dfn[x], dfn[y], id ); }node query( int num, int l, int r, int L, int R ) {if( L <= l && r <= R ) return t[num];int mid = ( l + r ) >> 1;pushdown( num );if( R <= mid ) return query( lson, l, mid, L, R );else if( mid < L ) return query( rson, mid + 1, r, L, R );else {node ans1 = query( lson, l, mid, L, R );node ans2 = query( rson, mid + 1, r, L, R );node ans;ans.l = ans1.l, ans.r = ans2.r;ans.cnt = ans1.cnt + ans2.cnt - ( ans1.r == ans2.l );return ans;} }int query( int x, int y ) {node t;int ans = dep[x] + dep[y], tot = 0;int last_x = -1, last_y = -1;while( top[x] ^ top[y] ) {if( dep[top[x]] >= dep[top[y]] ) {t = query( 1, 1, n, dfn[top[x]], dfn[x] );tot += t.cnt;if( last_x == t.r ) tot --;last_x = t.l;x = f[top[x]];}else {t = query( 1, 1, n, dfn[top[y]], dfn[y] );tot += t.cnt;if( last_y == t.r ) tot --;last_y = t.l;y = f[top[y]];}}if( dep[x] > dep[y] ) swap( x, y ), swap( last_x, last_y );ans -= ( dep[x] << 1 );t = query( 1, 1, n, dfn[x], dfn[y] );tot += t.cnt;if( t.l == last_x ) tot --;if( t.r == last_y ) tot --;return ans - tot + 1; }int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d %d", &n, &m );cnt = 0;for( int i = 1;i <= n;i ++ )G[i].clear(), son[i] = 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 );build( 1, 1, n );for( int i = 1, opt, a, b;i <= m;i ++ ) {scanf( "%d %d %d", &opt, &a, &b );if( opt & 1 ) modify( a, b, i + n );else printf( "%d\n", query( a, b ) );}}return 0; }

路徑交點

description

solution

  • 圖中的每個頂點至多出現在一條路徑中是對本題正解算法的條件限制/保證

  • (Pj?Qj)×(Pj+1?Qj+1)<0(P_j-Q_j)\times(P_{j+1}-Q_{j+1})<0(Pj??Qj?)×(Pj+1??Qj+1?)<0

    當固定第jjj層的枚舉順序時,發現這個條件限制的本質是逆序對

  • 詢問有偶數個交點的路徑方案數比有奇數個交點的路徑方案數多多少個

    一種方案的貢獻顯然是(?1)cnt,cnt(-1)^{cnt},cnt(?1)cnt,cnt表示這種方案下的逆序對個數

  • 相鄰層給出的若干條有向邊,可以構建一個鄰接矩陣

  • 綜上所有的信息都在暗示/匹配矩陣的行列式

    ∣P∣=∑j1,j2,...,jn(?1)τ(j1,j2...jn)a1,j1...an,jn|P|=\sum_{j_1,j_2,...,j_n}(-1)^{\tau(j_1,j_2...j_n)}a_{1,j_1}...a_{n,j_n}P=j1?,j2?,...,jn??(?1)τ(j1?,j2?...jn?)a1,j1??...an,jn??

    ∑j1,j2,...,jn:j\sum_{j_1,j_2,...,j_n}:jj1?,j2?,...,jn??:jnnn級全排列求和,τ(j1,j2,...,jn)\tau(j_1,j_2,...,j_n)τ(j1?,j2?,...,jn?)表示排列j1,...,jnj_1,...,j_nj1?,...,jn?的逆序對個數

  • 知道二分圖的解決方法了,接下來要擴展成kkk層圖的計算

    binet-cauchy公式 ∣AB∣=∣A∣∣B∣|AB|=|A||B|AB=AB

    所以只需要算出相鄰兩層的矩陣,然后矩陣乘法得到最后為n1×n1n_1\times n_1n1?×n1?的總矩陣

    最后通過高斯消元(上三角矩陣)計算主對角線的乘積就是矩陣的行列式,也是詢問的答案

code

#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define mod 998244353 #define int long long #define maxn 205 struct matrix {int n, m;int c[maxn][maxn];matrix() {n = m = 0;memset( c, 0, sizeof( c ) );}void clear() {for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ )c[i][j] = 0;}matrix operator * ( matrix &t ) const {matrix ans;ans.n = n, ans.m = t.m;for( int i = 1;i <= n;i ++ )for( int k = 1;k <= m;k ++ )if( c[i][k] )for( int j = 1;j <= t.m;j ++ )ans.c[i][j] = ( ans.c[i][j] + c[i][k] * t.c[k][j] ) % mod;return ans;} }last, now;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }void gauss( int a[][maxn], int n ) {int ans = 1;for( int i = 1;i <= n;i ++ ) {int k = i;for( int j = i + 1;j <= n;j ++ )if( a[j][i] > a[k][i] ) k = j;if( i ^ k ) swap( a[i], a[k] ), ans *= -1;for( int j = i + 1;j <= n;j ++ ) {int t = a[j][i] * qkpow( a[i][i], mod - 2 ) % mod;for( int k = i;k <= n;k ++ )a[j][k] = ( a[j][k] - t * a[i][k] % mod + mod ) % mod;}}for( int i = 1;i <= n;i ++ )ans = ans * a[i][i] % mod;printf( "%lld\n", ( ans + mod ) % mod ); }int T, n; int vec[maxn], edge[maxn]; signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ )scanf( "%lld", &vec[i] );for( int i = 1;i < n;i ++ )scanf( "%lld", &edge[i] );last.n = vec[1], last.m = vec[2], last.clear();for( int i = 1, u, v;i <= edge[1];i ++ ) {scanf( "%lld %lld", &u, &v );last.c[u][v] = 1;}for( int i = 2;i < n;i ++ ) {now.n = vec[i], now.m = vec[i + 1], now.clear();for( int j = 1, u, v;j <= edge[i];j ++ ) {scanf( "%lld %lld", &u, &v );now.c[u][v] = 1;}last = last * now;}gauss( last.c, vec[1] );}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的[NOI2021 day1]轻重边(树链剖分),路径交点(矩阵行列式)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 最新色网站 | 天堂网久久 | 日韩一页| 国产又粗又猛又爽又黄av | 麻豆亚洲av成人无码久久精品 | 清纯唯美亚洲 | 97超碰碰 | 天天插天天干 | 在线免费观看成人 | 99热久久这里只有精品 | 超碰97色| 小日子的在线观看免费第8集 | 国产无码精品在线播放 | 国产一级特黄aaa大片 | 在线精品一区二区三区 | 最新精品国产 | 婷婷综合在线视频 | 免费视频福利 | 91精品国产乱码久久 | 色网在线视频 | 免费啪啪网| 国产乱淫av麻豆国产免费 | 极品少妇xxxx精品少妇偷拍 | 三级全黄的视频 | 亚洲涩涩在线 | 黄视频网站在线观看 | 日本黄大片在线观看 | 草青青视频| 欧美国产激情 | 六月色丁香 | 玖草在线视频 | 最新av网址在线观看 | 国产乱码精品一区二区三 | 在线国产播放 | 在线看片国产 | 国产无遮挡a片又黄又爽 | 毛片视频网站 | 日韩天堂网 | 自拍天堂 | 精品一区李梓熙捆绑 | 中文字字幕在线中文乱码电影 | 伊人蕉久影院 | 亚洲电影在线看 | 黄色毛毛片 | 福利一区在线观看 | www色亚洲 | 国产伦精品一区二区三区免费 | 午夜激情网址 | 天天干狠狠爱 | 人人搞人人干 | 好男人www社区在线视频夜恋 | 欧美精品aaa| 在线麻豆视频 | 中日韩欧美在线观看 | 松本一香在线播放 | 最新中文字幕2019 | 暧暧视频在线观看 | 国产麻豆一区二区三区在线观看 | 五月婷婷开心网 | 亚洲成人一区在线观看 | 久在线播放 | 熟妇人妻中文av无码 | 欧美少妇b| 日韩少妇一区二区 | 国产午夜精品一区 | 国产精品久久久久毛片大屁完整版 | 久久你懂的| 欧美大胆视频 | 狠狠综合网 | 日本a级片免费 | 亚洲精品在线免费观看视频 | 欧洲精品无码一区二区 | 天堂成人 | 少妇2做爰hd韩国电影 | 成人免费视频一区二区 | 影音先锋中文字幕第一页 | 人人干视频 | 国产又黄又 | 超碰免费看 | 关之琳三级全黄做爰在线观看 | 好吊操这里只有精品 | 日韩无码精品一区二区三区 | 亚洲福利二区 | 毛片在线视频 | 久久久黄色 | 最新国产精品自拍 | 黄色特级毛片 | free性满足hd国产精品久 | 热热色av| 天天干中文字幕 | 精品国产av无码 | 久久精精品久久久久噜噜 | 亚洲性一区 | 午夜草草| 夜色视频网 | 久久疯狂做爰流白浆xx | 91免费看片 | 成人午夜视频免费看 | 庆余年三 |