intmain(){ int n; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); int ct = 0; for (int i = 1; i <= n; i++) { int r = i; while (r < n && a[i] <= a[r + 1]) r++; b[a[i]] = ++ct, i = r; } for (int i = 1; i <= n; i++) { if (!b[i]) b[i] = ++ct; printf("%d ", b[i]); } }
B 动物园
考虑对于一个1操作,看作 u 作为左儿子, v 作为右儿子建立一个类似kruskal重构树的东西。
由于考虑种类狠毒瘤,而考虑概率很方便就可以考虑概率。
然后对于一次 1 操作, u 的动物保留的概率是$\frac{2}{3}$v 的动物保留的概率是$\frac{1}{3}$。
#include<algorithm> #include<cstring> #include<cstdio> #include<iostream> usingnamespace std; #define MAXN 100006 #define P 998244353 int n , m; vector<int> G[MAXN]; int dp[MAXN][2]; voiddfs( int u , int fa ){ dp[u][0] = 0 , dp[u][1] = 1; for( int v : G[u] ) if( v != fa ) dfs( v , u ), dp[u][0] += max( dp[v][0] , dp[v][1] ) , dp[u][1] += dp[v][0]; } voiddfs2( int u , int fa ){ int t0; for( int v : G[u] ) if( v != fa ) t0 = dp[u][0] - max( dp[v][0] , dp[v][1] ) , dp[v][0] += max( t0 , dp[u][1] - dp[v][0] ) , dp[v][1] += t0 , dfs2( v , u ); } intmain(){ cin >> n >> m; for( int i = 1 , u , v ; i < n ; ++ i ) scanf("%d%d",&u,&v) , G[u].push_back( v ) , G[v].push_back( u ); dfs( 1 , 1 ); dfs2( 1 , 1 ); for( int i = 1 ; i <= n ; ++ i ) dp[i][1] = max( dp[i][0] , dp[i][1] ); int kel = 0 , lst0 = dp[1][0] , lst1 = dp[1][1]; printf("%d\n",lst1); while( m --> 0 ) { scanf("%d",&kel); if( lst0 == lst1 ) lst1 = ( 1ll * n * lst0 % P + dp[kel][1] ) % P , lst0 = ( 1ll * n * lst0 + dp[kel][0] ) % P; else lst1 = lst0 = 1ll * n * lst1 % P; printf("%d\n",lst1); } }