[2019 牛客CSP-S提高组赛前集训营4题解] 复读数组(数论)+ 路径计数机(数上DP)+ 排列计数机(线段树+二项式定理)

文章目录

  • T1:复读数组
    • 题目
    • 题解
    • 代码实现
  • T2:路径计数机
    • 题目
    • 题解
    • 代码实现
  • T3:排列计数机
    • 题目
    • 题解
    • CODE

T1:复读数组

题目

有一个长为n×k的数组,它是由长为n的数组A1,A2,…,An重复k次得到的。
定义这个数组的一个区间的权值为它里面不同的数的个数,
现在,你需要求出对于这个数组的每个非空区间的权值之和。
答案对10^9+7取模
点击下载大样例
输入描述:
第一行两个整数n和k。
接下来一行n个整数,第i个整数为Ai
输出描述:
输出一个整数,表示答案。

示例1
输入
2 2
1 2
输出
16
说明
数组为1, 2, 1, 2
对于长为1的区间,共4个,权值为1
对于长度>1的区间,可以发现权值均为2,共6个
那么权值和为1×4+2×6=16

备注:
对于前10%的数据n≤5
对于前20%的数据n≤100
对于前40%的数据n≤1000
对于另外10%的数据n≤100,k=1
对于另外10%的数据n≤1000,k=1
对于另外10%的数据n≤105,k=1
对于所有数据,1≤n≤105,1≤k≤109,1≤Ai≤109

题解

我们来考虑某一个a[x]如果出现在一个区间[l,r][l,r][l,r],那么就会对这个区间贡献1
所以我们可以去找有多少个区间包含a[x],这些区间的贡献就会+1

但是马上我们就意识到一个区间可能多个a[x],则这个区间a[x]的贡献就多算了
于是我们调转思路,去找多少个区间不包含a[x]


先不考虑k的限制,就看[l,r][l,r][l,r]
在这里插入图片描述
观察这幅图,假设a[x]在区间出现的位置分别在a,b,c
那么不包含a[x]的区间会在哪些地方取呢??易得如下图:
在这里插入图片描述
红色区域就是不包含a[x]的所有可能区间,
接着我们来计算着一个区间中有多少种[l,r][l,r][l,r]
举栗说明:
假设a[x]出现在4,12,那么[5,10][5,10][5,10]就是可选的区间,对于不同的l,对应的r个数也不一样

lr
55,6,7,8,9,10
66,7,8,9,10
77,8,9,10
88,9,10
99,10
1010

有木有发现规律,这其实就是一个等差数列,令T=b-a-1(真正能选区间的端点个数)
则答案个数就是T∗(T+1)/2T*(T+1)/2T(T+1)/2


接下来我们把k的限制考虑进去,看图↓
在这里插入图片描述
如果[1,n][1,n][1,n]的黄色区间就对应[n+1,2n][n+1,2n][n+1,2n][2n+1,3n][2n+1,3n][2n+1,3n]中的黄色区间
是不是他们是完全相等的,[1,n][1,n][1,n]中黄色区间的答案个数就是后面对应区间的个数
那么一个有k个这样的区间,所以…是不是乘个k

怎么算呢?肯定是上面说的等差数列,那么这个区间端点个数T又有多少个呢?(r−l−1)(r-l-1)(rl1)
举个栗子:a[x]出现在4,12,则可选端点就是[5,11][5,11][5,11],可取的左右端点就是l+1l+1l+1r−1r-1r1
即是(r−1−(l+1)+1)=(r−l−1)(r-1-(l+1)+1)=(r-l-1)(r1(l+1)+1)=(rl1)


如果是交叉了两个块怎么办呢??如图↓
在这里插入图片描述
与上面情况一样处理,但是我们发现这个时候只会有k-1个,所以…懂了吧!

怎么算呢?照样是等差数列,但是端点个数T发生了改变
推理一波:能跨块的区间是不是a[x]在[1,n][1,n][1,n]区间最后一次出现的位置到a[x]在[1,n][1,n][1,n]第一次出现的位置
只不过此时a[x]相对应在了第二个区间块

考虑在第一个区间块的可取端点为[l+1,n][l+1,n][l+1,n],个数就是n−(l+1)+1=n−ln-(l+1)+1=n-ln(l+1)+1=nl
考虑跨越在了第二个区间块的可取端点为[1,r−1][1,r-1][1,r1],个数就是r−1−1+1=r−1r-1-1+1=r-1r11+1=r1
把二者加在一起即是所有可取的端点个数了


代码实现

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define mod 1000000007
#define LL long long
#define MAXN 100005
struct node {int id, val;
}b[MAXN];
vector < int > G[MAXN];
int n;
int a[MAXN];
LL result, k, tot;bool cmp ( node x, node y ) {return x.val < y.val;
}LL count ( LL x ) {return ( ( x * ( x + 1 ) ) >> 1 ) % mod;
}int main() {scanf ( "%d %lld", &n, &k );for ( int i = 1;i <= n;i ++ ) {scanf ( "%d", &a[i] );b[i].val = a[i];b[i].id = i;}sort ( b + 1, b + n + 1, cmp );for ( int i = 1;i <= n;i ++ )if ( b[i].val != b[i - 1].val )a[b[i].id] = ++ tot;elsea[b[i].id] = tot;for ( int i = 1;i <= n;i ++ )G[a[i]].push_back( i );result = tot * count ( k * n % mod ) % mod;for ( int i = 1;i <= tot;i ++ ) {for ( int j = 1;j < G[i].size();j ++ )result = ( result - k * count ( G[i][j] - G[i][j - 1] - 1 ) % mod + mod ) % mod;result = ( result - ( k - 1 ) * count ( n - G[i][G[i].size() - 1] + G[i][0] - 1 ) % mod + mod ) % mod;result = ( result - count ( G[i][0] - 1 ) + mod ) % mod;result = ( result - count ( n - G[i][G[i].size() - 1] ) + mod ) % mod;}printf ( "%lld", result % mod );return 0;
} 

T2:路径计数机

题目

有一棵n个点的树和两个整数p, q,求满足以下条件的四元组(a, b, c, d)的个数:

  1. 1⩽a,b,c,d⩽n。
  2. 点a到点b的经过的边数为p。
  3. 点c到点d的经过的边数为q。
  4. 不存在一个点,它既在点a到点b的路径上,又在点c到点d的路径上。
    点击下载大样例

输入描述:
第一行三个整数n,p,q。
接下来n - 1行,每行两个整数u, v,表示树上存在一个连接点u和点v的边。
输出描述:
输出一个整数,表示答案。
示例1
输入
5 2 1
1 2
2 3
3 4
2 5
输出
4
说明
合法的四元组一共有:
(1, 5, 3, 4),
(1, 5, 4, 3),
(5, 1, 3 ,4),
(5, 1, 4, 3)。
示例2
输入
4 1 1
1 2
2 3
3 4
输出
8
备注:
对于前20%的数据,n,p,q≤50。
对于前40%的数据,n,p,q≤200。
对于另外10%的数据,p = 2, q = 2。
对于另外10%的数据,树是一条链。
对于另外10%的数据,树随机生成。
对于所有数据1≤n,p,q≤3000,1≤u,v≤n,保证给出的是一棵合法的树。

题解

其实这道题与集训营1的B题思路上很相似,下面就写得比较乱,如果想理解明白一点的,可以移步我之前的博客它会让你耳目一新,里面的讲解很清楚

话不多说,直接上思路,本蒟蒻还有很多题解没打
正难反易,考虑反求问题,不相交的路径数=所有路径数-相交路径数

思考哪些情况,存在一个点,它既在点a到点b的路径上,又在点c到点d的路径上
如果我们固定了a到b的路径,那么这个特殊的点会出现在哪里,肯定会经过lca(a,b)lca(a,b)lca(a,b)


情况1:c和d均在lca的子树内,两者相连必须经过lca
在这里插入图片描述
情况2:c和d通过lca相连
在这里插入图片描述
情况3:c和d在a到lca或者b到lca路径上相连
在这里插入图片描述
不难发现如果我们把a的父亲,lca的儿子假设成新的lca,上面的情况2和情况3都是一样的,而且c到d的绿色路径总是经过lca的
他可以是两条都在子树内的链或者是一条子树内的链和一条从子树内(可以不进)到子树外的链
这启示我们可以通过枚举lca来进行转移


dp[u][j]dp[u][j]dp[u][j]表示:u的子树内,与u的距离为j的节点个数
那么转移就很简单,通过儿子v完成
dp[u][j]+=dp[v][j−1]dp[u][j]+=dp[v][j-1]dp[u][j]+=dp[v][j1]
fp[u]fp[u]fp[u]表示:情况1两条都在子树内的链的距离为p的方案数量
那么每个点都会与u的其它子树链上点构成一种方案,所以我们可以规定顺序,x与之前搜索到的点进行匹配,后面的点再与前面的点进行匹配,这样就不会多算
fp[u]=dp[u][p−j]∗dp[v][j−1]fp[u]=dp[u][p-j]*dp[v][j-1]fp[u]=dp[u][pj]dp[v][j1]
这样保证了,一定会经过u成为lca的这个点
那么情况1中距离为q的方案数量与上面的转移则是一模一样,不再重复

接着设gp[v][j]gp[v][j]gp[v][j]表示:除开v的子树,整棵树与v的距离为j的节点个数,来处理情况2
我们用v的父亲u来更新v,v外面的点距离u的距离应该是j-1,那么会出现这种情况,与集训营1的一道题类似,在v的子树内的点距离v就不会是j-1,而应该是j-2,要减掉
在这里插入图片描述
g[v][j]+=g[u][j−1]+dp[u][j−1]−dp[v][j−2]g[v][j] += g[u][j - 1] + dp[u][j - 1] - dp[v][j - 2]g[v][j]+=g[u][j1]+dp[u][j1]dp[v][j2]
接着就是与上面一样的思路,边DP便进行更新
gp[u]+=dp[u][p−i]∗g[u][i]gp[u] += dp[u][p - i] * g[u][i]gp[u]+=dp[u][pi]g[u][i]
gq[u]+=dp[u][q−i]∗g[u][i]gq[u] += dp[u][q - i] * g[u][i]gq[u]+=dp[u][qi]g[u][i]
最后算出来的方案数要∗4*44,因为点对顺序不一样算不同的方案,看样例就可知了

代码实现

#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
#define MAXN 3005
#define LL long long
vector < int > G[MAXN];
int n, p, q;
LL result;
LL dp[MAXN][MAXN], fp[MAXN], fq[MAXN], g[MAXN][MAXN], gp[MAXN], gq[MAXN];void dfs1 ( int u, int fa ) {dp[u][0] = 1;for ( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if ( v == fa )continue;dfs1 ( v, u );for ( int j = 1;j <= p;j ++ )fp[u] += dp[u][p - j] * dp[v][j - 1];for ( int j = 1;j <= q;j ++ )fq[u] += dp[u][q - j] * dp[v][j - 1];for ( int j = 1;j <= p;j ++ )dp[u][j] += dp[v][j - 1];}
}void dfs2 ( int u, int fa ) {for ( int i = 1;i <= p;i ++ )gp[u] += dp[u][p - i] * g[u][i];for ( int i = 1;i <= q;i ++ )gq[u] += dp[u][q - i] * g[u][i];for ( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if ( v == fa )continue;g[v][1] = 1;for ( int j = 2;j <= p;j ++ )g[v][j] += g[u][j - 1] + dp[u][j - 1] - dp[v][j - 2];dfs2 ( v, u );}
}int main() {scanf ( "%d %d %d", &n, &p, &q );if ( p < q )swap ( p, q );for ( int i = 1;i < n;i ++ ) {int u, v;scanf ( "%d %d", &u, &v );G[u].push_back( v );G[v].push_back( u );}dfs1 ( 1, 0 );dfs2 ( 1, 0 );LL sum1 = 0, sum2 = 0;for ( int i = 1;i <= n;i ++ )sum1 += fp[i], sum2 += fq[i];result = sum1 * sum2;for ( int i = 1;i <= n;i ++ )result -= fp[i] * fq[i] + fp[i] * gq[i] + fq[i] * gp[i];printf ( "%lld\n", result * 4 );return 0;
}

T3:排列计数机

题目

定义一个长为k的序列A1,A2,…,AkA_1, A_2, \dots, A_kA1,A2,,Ak的权值为:对于所有1≤i≤k,max⁡(A1,A2,…,Ai)1 \le i \le k,\max(A_1, A_2, \dots, A_i)1ikmax(A1,A2,,Ai)有多少种不同的取值。
给出一个1到n的排列B1,B2,…,BnB_1, B_2, \dots, B_nB1,B2,,Bn,求B的所有非空子序列的权值的m次方之和。
答案对109+710^9 + 7109+7取模。

点击下载大样例
输入描述:
第一行两个整数n、m。
接下来一行n个整数,第i个整数为BiB_iBi
输出描述:
输出一个整数,表示答案。

示例1
输入
3 2
1 3 2
输出
16
说明
在所有非空子序列中:
(1), (3), (2), (3, 2)权值为1,
(1, 3), (1, 2), (1, 3, 2)权值为2。
那么所有非空子序列权值的2次方和为4×12+3×22=164 \times 1^2 + 3 \times 2^2 = 164×12+3×22=16
备注:
对于前10%10\%10%的数据,n≤20n \le 20n20
对于前20%20\%20%的数据,n≤100n \le 100n100
对于前40%40\%40%的数据,n≤1000n \le 1000n1000
对于另外20%20\%20%的数据,m = 1。
对于所有数据,1≤n≤1051 \le n \le 10^51n1051≤m≤201 \le m \le 201m20,保证B是1到n的排列。

题解

考虑从左到右一个一个加入数
当加入一个数的时候,只有最大值小于这个数的子序列,权值才会被更新(+1+1+1
但我们不可能把每个子序列的权值都求出来后才乘方再加起来,三秒也会T得你怀疑人生
在这里插入图片描述
但我们根据二项式定理,可以发现对于任意一个数x
(x+1)m=Cm0xm+Cm1xm−1+Cm2xm−2+⋯⋯+Cmm−2x2+Cmm−1x1+Cmmx0(x+1)^m=C^0_mx^m+C^1_mx^{m−1}+C^2_mx^{m−2}+⋯⋯+C^{m−2}_mx^2+C^{m−1}_mx^1+C^m_mx^0(x+1)m=Cm0xm+Cm1xm1+Cm2xm2++Cmm2x2+Cmm1x1+Cmmx0
通过这个,启发我们可以维护每个子序列权值的m次方和,m-1次方和,m-2次方和…1次方和,0次方和,就可以通过上面的公式得到这些子序列权值集体加1后的乘方的和

由于每次插入值的时候更新只跟最大值有关,而且题目中保证了B是一个排列,因此分情况处理:
1.我们可以把最大值相同的子序列一起处理,维护它们的m次方和,m-1次方和,m-2次方和
加入一个新的数的时候,找到所有最大值比它小的子序列,将它们的m次方和,m-1次方和…加起来,再用二项式定理得到加1后的m次方和,得到一组新的子序列的信息

2.对于那些最大值比它大的子序列,因为无法更新但可以形成新的子序列,使得答案为x的子序列多了整整一倍,所以直接将和∗2*22就好了

这个可以用线段树维护,线段树的每个位置维护相同最大值的子序列的一些信息

CODE

#include <cstdio>
#define mod 1000000007
#define MAXN 100005
int n, m;
int a[MAXN], tmp[25], pre[25], sum[MAXN << 2][25], lazy[MAXN << 2][25];
//sum[i][k]维护的C(k,m)i^m和 
int C[25][25];void pushdown ( int t, int l, int r, int k ) {lazy[t << 1][k] = 1ll * lazy[t << 1][k] * lazy[t][k] % mod;lazy[t << 1 | 1][k] = 1ll * lazy[t << 1 | 1][k] * lazy[t][k] % mod;sum[t << 1][k] = 1ll * sum[t << 1][k] * lazy[t][k] % mod;sum[t << 1 | 1][k] = 1ll * sum[t << 1 | 1][k] * lazy[t][k] % mod;lazy[t][k] = 1;return;
}void add ( int t, int l, int r, int id, int v, int k ) {if ( l == r ) {sum[t][k] = v;return;}int mid = ( l + r ) >> 1;pushdown ( t, l, r, k );if ( id <= mid )add ( t << 1, l, mid, id, v, k );elseadd ( t << 1 | 1, mid + 1, r, id, v, k );sum[t][k] = ( sum[t << 1][k] + sum[t << 1 | 1][k] ) % mod;
}int query ( int t, int l, int r, int id, int k ) {if ( r <= id )return sum[t][k];int mid = ( l + r ) >> 1;pushdown ( t, l, r, k );int sum1 = 0, sum2 = 0;sum1 = query ( t << 1, l, mid, id, k );if ( mid < id )sum2 = query ( t << 1 | 1, mid + 1, r, id, k );return ( sum1 + sum2 ) % mod;
}void mul ( int t, int l, int r, int id, int k ) {if ( r < id )return;if ( id <= l ) {sum[t][k] = 2ll * sum[t][k] % mod;lazy[t][k] = lazy[t][k] * 2ll % mod;return;}int mid = ( l + r ) >> 1;pushdown ( t, l, r, k );if ( id <= mid )mul ( t << 1, l, mid, id, k );mul ( t << 1 | 1, mid + 1, r, id, k );sum[t][k] = ( 1ll * sum[t << 1][k] + sum[t << 1 | 1][k] ) % mod;
}int main() {C[0][0] = 1;//先打出二项式定理C的表,仗着m小使劲搞for ( int i = 1;i <= 20;i ++ ) {C[i][0] = 1;for ( int j = 1;j <= i;j ++ )C[i][j] = C[i - 1][j - 1] + C[i - 1][j];}scanf ( "%d %d", &n, &m );for ( int i = 1;i <= ( n << 2 );i ++ )for ( int j = 0;j <= m;j ++ )lazy[i][j] = 1;//线段树初始化,因为我们是乘法所以初始化为1 for ( int i = 1;i <= n;i ++ ) {scanf ( "%d", &a[i] );for ( int j = 0;j <= m;j ++)pre[j] = tmp[j] = 0;for ( int j = 0;j <= m;j ++ )pre[j] = query ( 1, 1, n, a[i], j );for ( int j = m;j >= 0;j -- )for ( int k = j;k >= 0;k -- )tmp[j] = ( tmp[j] + 1ll * pre[k] * C[j][k] % mod ) % mod;for ( int j = 0;j <= m;j ++ ) {add ( 1, 1, n, a[i], tmp[j] + 1, j );mul ( 1, 1, n, a[i] + 1, j );}}printf ( "%d", ( query ( 1, 1, n, n, m ) % mod + mod ) % mod );return 0;
}

在这里插入图片描述终于补了这道题,这篇blog也算是有头的了,就bb咯!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模板:(多重)哈希

前言 还在为不想写双哈希又怕哈希冲突挂掉发愁吗&#xff1f; 来这里&#xff0c;满足你的一切梦想&#xff01; 哈希还有模板&#xff1f; 其实就是把相关的函数和数组打包到一个结构体里 但是针心方便啊&#xff01;&#xff01;&#xff01; 如果想双哈希的话&#xff0c;定…

CF1183H Subsequences (hard version)

题意&#xff1a; 长度为n的字符串S&#xff0c;现在要找出k个不同的子序列&#xff0c;使得这些序列的总价值最低 一个序列的价值等于删去的字符长度&#xff08;空串也算子序列&#xff09; 1≤n≤100,1≤k≤1012 题解&#xff1a; 一看就是dp&#xff0c;我们先想想串a可…

P7888-「MCOI-06」Distinct Subsequences【dp】

正题 题目大意 给出一个长度为nnn的字符串aaa&#xff0c;求它的所有子序列的本质不同子序列个数。 1≤n≤1061\leq n\leq 10^61≤n≤106 解题思路 考虑每个子序列产生的贡献&#xff0c;为了防止算重我们一个只统计走子序列自动机上的边的子序列&#xff0c;也就是说对于TTT…

微软携手 Docker 打造 CNAB,分布式应用来了!

微软中国MSDN 前天Microsoft Connect(); 2018发布的众多最新科技&#xff0c;都让全球开发者惊艳不已。其中一项最令开发者瞩目并迫不及待——微软联合Docker发布了云本地应用捆绑包&#xff08;Cloud Native Application Bundle&#xff0c;以下简称CNAB&#xff09;&#xff…

9.4 模拟

前言 175分 60100150 T3和T4做的不好 T4没有理解题目的意思…qwq T3暴力似乎挂了… 但T1和T2还是不戳的 T1打表找规律的方法也许更为有效 考场 先看题。 药丸。。 T3、4甚至根本没有看懂… T1和T2也感觉挺玄乎的 有一种爆零的预感 8&#xff1a;10 先看T1 推了推似乎还是有…

P4135 作诗

P4135 作诗 题意&#xff1a; 给定 n 个不大于 c 的正整数 a1…an 和 m 组询问&#xff0c;每次问 [l,r] 中有多少个数出现正偶数次。 对于每次询问&#xff1a; 设上一个询问的答案为 ans&#xff08;第一个询问时 ans0&#xff09;&#xff0c;令L(lans)mod n1&#xff0c;…

[C++]试一试结构体struct node的构造函数

可直接点击跳转到构造函数处结构体概念定义结构体定义结构体及结构体变量结构体变量的特点成员调用成员函数调用结构体的构造函数Upd1Upd2Upd3结构体概念 在实际问题中&#xff0c;一组数据往往具有不同的数据类型。 例如&#xff1a;人口大普查时&#xff0c;需要记录每一个人…

CSP-S 2021 退役记

写的比较草率&#xff0c;但的确是真实感受。 10.23 回寝室前敲了一个 dinic 板子&#xff0c;觉得不会考。。。 10.24 8:00 起床&#xff0c;还好今天宿管不在&#xff0c;可以起的晚一点。 吃了早饭来机房颓废。 10:00 似乎考前反而不知道该如何复习了&#xff0c;翻了翻以前…

Ybtoj-排列计数【矩阵乘法,分块幂】

正题 题目链接:http://noip.ybtoj.com.cn/contest/596/problem/1 题目大意 TTT组询问给出nnn求有多少个nnn的排列满足第一个是111并且相邻的差不超过222。 1≤T≤106,1≤n≤1091\leq T\leq 10^6,1\leq n\leq 10^91≤T≤106,1≤n≤109 解题思路 考虑一下如果我们要不断向前填满…

[多校联考-西南大学附中]切面包(线段树/概率与期望)+ Slow Path Finding Algorithm(拓扑排序/DP)+ 分数转化(数论)

文章目录T1&#xff1a;分数转换题目题解代码实现T2&#xff1a;Slow Path Finding Algorithm题目题解代码实现T3&#xff1a;切面包题目题解代码实现T1&#xff1a;分数转换 题目 Time limit: 1.5 seconds Memory limit: 512 megabytes 给定一个十进制小数&#xff0c;请你…

P3992 [BJOI2017]开车

P3992 [BJOI2017]开车 题意&#xff1a; 题解&#xff1a; 我们要先将问题转换 圈是车&#xff0c;x是加油站。红色部分为车移动的路线 数组a是车数量的前缀和 数组b是加油站的前缀和 而a[i]与b[i]的差的绝对值就是对应的红色路被走的次数 现在车发生位置移动&#xff0c;b数…

IdentityServer4-MVC+Hybrid实现Claims授权验证(四)

上节IdentityServer4-客户端的授权模式原理分析&#xff08;三&#xff09;以对话形式&#xff0c;大概说了几种客户端授权模式的原理&#xff0c;这节重点介绍Hybrid模式在MVC下的使用。且为实现IdentityServer4从数据库获取User进行验证&#xff0c;并对Claim进行权限设置打下…

9.05 模拟

文章目录前言考场复盘T2T4总结前言 290分 1003010060 整体来说还不错&#xff0c;没有挂分 但是T2应该可以拿到值域[1,000]的第二档写到60分的 一部分原因也是给T2的时间有点少 &#xff08;十分钟&#xff09; 本次第一次尝试了在考场上对拍 效果还是不错的&#xff0c;并不会…

李超线段树

李超线段树可以用来维护平面上的线段(但是要求 \(x\) 或 \(y\) 其中一维比较小&#xff0c;在 \(10^5\) 及以内)。 称一条线段能成为区间 \([l,r]\) 中的最优线段&#xff0c;当且仅当&#xff1a; 该线段的定义域完整覆盖了区间 \([l,r]\) &#xff1b; 该线段在区间中点处最…

2021牛客OI赛前集训营-树数树【树上启发式合并,堆】

正题 题目链接:https://ac.nowcoder.com/acm/contest/20107/C 题目大意 给出nnn个点的一棵树&#xff0c;求一个最长的序列使得数字互不相同且相邻编号节点的都是祖孙关系。 1≤n≤105,1≤T≤51\leq n\leq 10^5,1\leq T\leq 51≤n≤105,1≤T≤5 解题思路 wx,iw_{x,i}wx,i​表…

漫谈何时从单体架构迁移到微服务?

面对微服务如火如荼的发展&#xff0c;很多人都在了解&#xff0c;学习希望能在自己的项目中帮得上忙&#xff0c;当你对微服务的庐山真面目有所了解后&#xff0c;接下来就是说服自己了&#xff0c;到底如何评估微服务&#xff0c;什么时候使用微服务&#xff0c;什么时间点最…

模版:线段树合并+线段树分裂

文章目录前言合并代码分裂代码前言 话说天下之树&#xff0c;分久必合&#xff0c;合久必分 合并 所谓合并&#xff0c;就是把两个树合并 以把B树合并到A树为例 如果A没有该节点&#xff0c;改成B的该节点返回 如果B没有该节点&#xff0c;直接返回 否则递归合并子树&#xff…

2021牛客OI赛前集训营-方格计数【计数,dp】

正题 题目链接:https://ac.nowcoder.com/acm/contest/20107/B 题目大意 给出一个whw\times hwh的网格图&#xff0c;然后要求在上面选出nnn个格点&#xff0c;使得它们在一条直线上且两两之间距离不小于ddd。 1≤T≤20,1≤w,h,d≤500,1≤n≤501\leq T\leq 20,1\leq w,h,d\leq…

可持久化并查集

蒟蒻比较菜&#xff0c;现在才学。。。 P3402 可持久化并查集 其实就是魔改的主席树啦&#xff0c;记录每个点的直接父亲与这棵子树的大小。 合并的时候不用路径压缩&#xff0c;直接暴力跳父亲&#xff0c;\(O(\log^2)\) 找到祖先&#xff0c;之后启发式合并(启发式合并的平均…

[CSP-S Day1,Day2 游记]提高组考后总结及学习编程C++以来的心得体会

怀着沉重而感慨的心情写下了这篇blog考试中暴露的问题Day1Day2综上解决方法学习历程及以来的心得体会职业精神这篇博客我可能会写好几天&#xff0c;我jio得这篇博客对我的学习历程以及态度产生深刻影响考试中暴露的问题 首先先说这次提高组考试的每道题所遇到的各种问题吧 Da…