国内最大c2c网站网站服务器一年的费用
国内最大c2c网站,网站服务器一年的费用,html教程菜鸟教程下载,唐山网站关键词优化NOI 2021 day1轻重边descriptionsolutioncode路径交点descriptionsolutioncode轻重边
description
solution case1~6 把父亲和儿子的边转化为储存在儿子上的点 建树#xff0c;暴力爬lcalcalca#xff0c;暴力修改#xff0c;O(n2)O(n^2)O(n2) caseA 对于一条链的情况1~6 把父亲和儿子的边转化为储存在儿子上的点 建树暴力爬lcalcalca暴力修改O(n2)O(n^2)O(n2) caseA 对于一条链的情况每次修改重边就是一段区间轻边只有两个端点相连的边 同样的边化点线性用线段树区间/单点修改区间查询 caseB 第二类操作询问只有一条边考虑这条边怎么才可能是重边显然就是两个点最后被经过的时间戳要一样 树链剖分打时间戳 case1~20 正解其实就在caseB基础上的确一条边如果是轻边当且仅当该边的两个端点所打时间戳不同 树链剖分维护数颜色段的个数轻边的数量重边数量减一下就可以了 最原始局面全都是轻边所以初始化建树时就要给每个点打一个不同的时间戳
蒟蒻只想到所有到caseB的前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)×(Pj1−Qj1)0(P_j-Q_j)\times(P_{j1}-Q_{j1})0(Pj−Qj)×(Pj1−Qj1)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}:j∑j1,j2,...,jn:j的nnn级全排列求和τ(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∣∣A∣∣B∣ 所以只需要算出相邻两层的矩阵然后矩阵乘法得到最后为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;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/86897.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!