迎开学水题狂欢赛(舞踏会[dp+三叉树],HH去散步[矩阵快速幂],排序[模拟],铁路旅行[线段树])

快速简单记录老师口胡(可能就我自己看得懂了吧…)
在这里插入图片描述

文章目录

  • T1:舞踏会
    • title
    • solution
    • code
  • T2:HH去散步
    • title
    • solution
    • code
  • T3:排序
    • title
    • solution
    • code
  • T4:铁路旅行
    • title
    • solution
    • code

T1:舞踏会

title

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

solution

对于三个人中间取中值的操作,我们可以把它弄到树上去,搞成一个三叉树
然后可以任意乱排不固定人的位置的话,也就意味着这个三叉树的形态是多变的
在这里插入图片描述

接着我们来定义一下这个树上的规则,对于点fafafa 而言,他的三个儿子的权值要满足:左儿子<=中儿子<=右儿子,即ls≤ms≤rsls\le ms\le rslsmsrs
但是左儿子的右儿子就不一定也要小于fafafa的值,这个大小关系是不会传递祖宗八代都保持的哦!
这样对于该点的答案权值,直接取中间儿子的值就可以了
在这里插入图片描述
可知从fafafa 开始一直往右走或者往下走,这一路上的值都应该大于等于fafafa,也就是说这条路经过了多少个点就必须要满足多少个点的值>=fa>=fa>=fa,这个fafafa的值才可能成为答案
我们定义这些点为坑,需要填充
(如果本身就有值固定了,就需要看是否>=fa>=fa>=fa
而从fafafa 开始一直往左走或者往下走,这一路上的值都应该小于等于fafafa

为了让答案更大,我们就想要坑的个数越小越好,同时要保证左子树也满足要求

code

/*
序列的1~3位以第n+1位为父节点
表示1~3位的中值会移动到第n+1位
序列的4~6位以第n+2位为父节点
以此类推......
可知点i的三个儿子分别为(i-n)*3-2, (i-n)*3-1,(i-n)*3
我们称必须大于等于答案并且没人的叶子节点为坑
显然根到每个坑的路径上没有向左的边
*/
#include <cstdio>
#include <iostream> 
#include <algorithm>
using namespace std;
#define MAXN 100005
#define INF 0x3f3f3f3f
//不能定义成0x7f7f7f7f因为后面min比较会涉及加法
//两个int上界相加则会爆出int成为负的
struct node {int val, num, rk;
}nobel[MAXN];
int n, m, N;
int p[MAXN], v[MAXN], dp[MAXN << 1];
/*
val能力值 num编号 rk排名
p[i]编号为i的位置(没有就为0)
v[i]位置为i的排名
dp[i]以i为根的子树 最少坑的数量 
n人数 N树上节点总数 也是整棵树的根 
*/
bool cmpVal ( node x, node y ) {return ( x.val == y.val ) ? x.num < y.num : x.val < y.val;
}bool cmpNum ( node x, node y ) {return x.num < y.num;
}void dfs ( int u, int ans ) {if ( u <= n ) {//u为叶子节点 if ( ! v[u] )//位置上没人需要填一个坑dp[u] = 1;else if ( v[u] >= ans )//位置上有一个满足条件的人则不需要填坑dp[u] = 0;else//不满足条件->u不能成为右子树或者中子树(非法)dp[u] = INF;//dp关于ans呈单调递增//ans越大->对v[u]的要求越高->dp[u]=0的难度就越高 }else {int t = u - n;for ( int i = t * 3 - 2;i <= t * 3;i ++ )dfs ( i, ans );dp[u] = INF;dp[u] = min ( dp[t * 3 - 2] + dp[t * 3 - 1], dp[u] );dp[u] = min ( dp[t * 3 - 2] + dp[t * 3], dp[u] );dp[u] = min ( dp[t * 3 - 1] + dp[t * 3], dp[u] );//dp关于ans呈单调递增 }
}int main() {scanf ( "%d %d", &n, &m );N = n + ( n >> 1 );//共有n/2个非叶节点//一共要淘汰n-1个人 每三个人当中淘汰两个//一个非叶节点代表三进一//所以淘汰次数为(n-1)/2 非叶节点个数也应为(n-1)/2//n又保证是奇数所以(n-1)/2=n/2 for ( int i = 1;i <= n;i ++ ) {scanf ( "%d", &nobel[i].val );nobel[i].num = i;if ( i <= m ) scanf ( "%d", &p[i] );}sort ( nobel + 1, nobel + n + 1, cmpVal );for ( int i = 1;i <= n;i ++ )nobel[i].rk = i;//按照能力排序后的排名sort ( nobel + 1, nobel + n + 1, cmpNum );for ( int i = 1;i <= m;i ++ )v[p[i]] = nobel[i].rk;int l = 1, r = n;while ( l != r ) {int mid = ( l + r + 1 ) >> 1;dfs ( N, mid );int tot = 0;//能力值>=mid的人数 用来填坑的数量//tot关于mid呈单调递减 //mid越大->rk>=mid难度越高->tot++越难触发for ( int i = m + 1;i <= n;i ++ )if ( nobel[i].rk >= mid ) tot ++;if ( dp[N] <= tot )//坑的数量比填坑的数量小则可以实现l = mid;elser = mid - 1; }sort ( nobel + 1, nobel + n + 1, cmpVal );printf ( "%d\n", nobel[l].val );return 0;
}

T2:HH去散步

title

HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。 现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

输入格式
第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。 接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai != Bi,但不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。

输出格式
一行,表示答案。

样例
Sample Input
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
Sample Output
4

数据范围与提示
对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。 对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B < N。

solution

看到n,mn,mn,mttt完全不在一个量级的时候,一般都会想矩阵加速等玩意儿
假设原矩阵A[1][i]A[1][i]A[1][i]表示从起点走到iii点的方案数,加速矩阵B[i][j]B[i][j]B[i][j]表示i−>ji->ji>j存在一条有向边可以这么走
注意无向边拆开的两条边不要连在一起
由于起点aaa可以一开始任意走连出去的边,所以它没有加速矩阵的统一,我们就单独算一次,加速矩阵就少做一次即可
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define MAXN 150
#define mod 45989
int cnt = 1, result;struct Matrix {int c[MAXN][MAXN];Matrix () {memset ( c, 0, sizeof ( c ) );}Matrix operator * ( const Matrix &a ) const {Matrix ans;for ( int i = 1;i <= cnt;i ++ )for ( int j = 1;j <= cnt;j ++ )for ( int k = 1;k <= cnt;k ++ )ans.c[i][j] = ( ans.c[i][j] + 1ll * c[i][k] * a.c[k][j] % mod ) % mod;return ans;}
}A, B;Matrix qkpow ( Matrix a, int b ) {Matrix ans;for ( int i = 1;i <= cnt;i ++ )ans.c[i][i] = 1;while ( b ) {if ( b & 1 ) ans = ans * a;a = a * a;b >>= 1;}return ans;
}int n, m, t, a, b;
int from[MAXN], to[MAXN];void add ( int u, int v ) {from[++ cnt] = u; to[cnt] = v;from[++ cnt] = v; to[cnt] = u;
}int main() {scanf ( "%d %d %d %d %d", &n, &m, &t, &a, &b );a ++; b ++;for ( int i = 1;i <= m;i ++ ) {int u, v;scanf ( "%d %d", &u, &v );u ++; v ++;add ( u, v );}for ( int i = 1;i <= cnt;i ++ )if ( from[i] == a ) A.c[1][i] ++;for ( int i = 1;i <= cnt;i ++ )for ( int j = 1;j <= cnt;j ++ )if ( to[i] == from[j] && i != ( j ^ 1 ) && i != j )B.c[i][j] ++;B = qkpow ( B, t - 1 );A = A * B;for ( int i = 1;i <= cnt;i ++ )if ( to[i] == b ) result = ( result + A.c[1][i] ) % mod;printf ( "%d", result );return 0;
}

T3:排序

title

在这里插入图片描述
在这里插入图片描述

solution

有一个结论:操作顺序的调换对最后的答案没有影响
可以感性理解,自己画画反正就是举不出反例(摊手无奈┓( ´∀` )┏)
有了这个结论我们就可以知道,如果最后生成了一个不同的序列花费了xxx次操作,那么方案数就应该加上x!x!x!

接着题目的描述是每一次只能调换一次整体长度为2i2^i2i的两段序列,也可以不换
下一轮就是操作长度为2i+12^{i+1}2i+1

也就是说如果本轮有超过222段不合法的序列,就无法完成,这个时候就可以回溯了

所以我们必须保证在iii层的时候,答案序列分成长度2i−12^{i-1}2i1后的每一段内部都是有序的,这样在进行本轮操作后才有可能成功,举个栗子
12341\ 2\ 3\ 41 2 3 4
i=3:3214i=3:3\ 2\ 1\ 4i=3:3 2 1 4
可以发现必须要2i−12^{i-1}2i1整段整段调换,无论如何都无法凑出最后答案
因为他们的内部并不按从小到大有序
而如果是这个栗子就可以凑出答案
12341\ 2\ 3\ 41 2 3 4
i=3:3412i=3:3\ 4\ 1\ 2i=3:3 4 1 2

由此可见必须先进行长度为111的调换操作,然后进行长度为222的,以此类推才有可能保证对于iii层而言,内部是有序的

剩下的就看代码注释吧…
在这里插入图片描述

code

#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define MAXN 4100
int n, result;
int A[MAXN];void change ( int idx1, int idx2, int len ) {for ( int i = 0;i < len;i ++ )swap ( A[idx1 + i], A[idx2 + i] );
}
//注意:1234这种只是指类型,12是一种,34是一种
//比如2 3 || 9 10也符合12 34这种类型
void dfs ( int len, int x ) {if ( n == len ) {//所有类型的交换都已进行 满足的方案就有x! int ans = 1;for ( int i = 1;i <= x;i ++ )ans *= i;result += ans;return;}int L = len << 1;int tot = 0;//不合法的个数int p[3];for ( int i = 1;i <= n;i += L ) {if ( A[i] % L != 1 || A[i + len] - A[i] != len ) {tot ++;if ( tot > 2 ) return;//超过两个就无法完成 p[tot] = i;}}switch ( tot ) {case 0 : dfs ( L, x ); break;case 1 : {//21类型 需交换成为12 change ( p[1], p[1] + len, len );dfs ( L, x + 1 );change ( p[1], p[1] + len, len );break;}case 2 : {if ( A[p[1]] % L == 1 && A[p[2]] % L == 1 ) {//14 32类型 change ( p[1] + len, p[2] + len, len );dfs ( L, x + 1 );//交换成为12 34 change ( p[1] + len, p[2] + len, len );change ( p[1], p[2], len );dfs ( L, x + 1 );//交换成为34 21 change ( p[1], p[2], len );}else if ( A[p[1]] % L == 1 && A[p[1] + len] % L == 1 ) {if ( A[p[2] + len] - A[p[1] + len] == len ) {//13 24类型 (只能用4-3或者2-1判断类型!不能用3-2)//比如2 5 3 6也是符合13 24类型,这个时候5-3就≠1)//下面的判断同理change ( p[1] + len, p[2], len );dfs ( L, x + 1 );//交换成为12 34 change ( p[1] + len, p[2], len );}}else if ( A[p[2]] % L == 1 && A[p[2] + len] % L == 1 ) {//42 31类型 if ( A[p[1]] - A[p[2]] == len ) {//这个判断等价于A[p[1]+len]-A[p[2]+len]=lenchange ( p[1], p[2] + len, len );dfs ( L, x + 1 );//交换成为12 34 change ( p[1], p[2] + len, len );}}break;}} 
}signed main() {scanf ( "%lld", &n );n = 1 << n;for ( int i = 1;i <= n;i ++ )scanf ( "%lld", &A[i] );dfs ( 1, 0 );printf ( "%lld", result );return 0;
}

T4:铁路旅行

title

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

solution

首先很容易想到:
对于第i条路而言,假设第i条路走了j次,那么我们的抉择就是:
min(A[i]∗j,B[i]∗j+C[i])min(A[i]*j,B[i]*j+C[i])min(A[i]j,B[i]j+C[i])
接着发现题目的铁路是一条单链且顺次连接
意味着对于点i,ji,ji,j,铁路i−ji-jij都要加1
这种区间操作我们很容易就想到了线段树操作
最后再单点查询每个点走的次数即可
(实在很简单,我都不会口胡了)
在这里插入图片描述

code

#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 100005
#define int long long
int n, m, result;
int a[MAXN], b[MAXN], c[MAXN], p[MAXN];
int tree[MAXN << 2], flag[MAXN << 2];void pushdown ( int t, int l, int r ) {if ( ! flag[t] ) return;int mid = ( l + r ) >> 1;tree[t << 1] += flag[t] * ( mid - l + 1 );tree[t << 1 | 1] += flag[t] * ( r - mid );flag[t << 1] += flag[t];flag[t << 1 | 1] += flag[t];flag[t] = 0;
}void add ( int t, int l, int r, int L, int R ) {if ( L <= l && r <= R ) {tree[t] += ( r - l + 1 );flag[t] ++;return;}pushdown ( t, l, r );int mid = ( l + r ) >> 1;if ( L <= mid ) add ( t << 1, l, mid, L, R );if ( mid < R ) add ( t << 1 | 1, mid + 1, r, L, R );tree[t] = tree[t << 1] + tree[t << 1 | 1];
}int query ( int t, int l, int r, int id ) {if ( l == r ) return tree[t];pushdown ( t, l, r );int mid = ( l + r ) >> 1;if ( id <= mid ) return query ( t << 1, l, mid, id );else return query ( t << 1 | 1, mid + 1, r, id );
}signed main() {scanf ( "%lld %lld", &n, &m );for ( int i = 1;i <= m;i ++ )scanf ( "%lld", &p[i] );for ( int i = 1;i < m;i ++ ) {int minn = min ( p[i], p[i + 1] );int maxx = max ( p[i], p[i + 1] );add ( 1, 1, n, minn, maxx - 1 );}for ( int i = 1;i < n;i ++ )scanf ( "%lld %lld %lld", &a[i], &b[i], &c[i] );for ( int i = 1;i < n;i ++ ) {int tot = query ( 1, 1, n, i );if ( tot * ( a[i] - b[i] ) < c[i] )result += tot * a[i];elseresult += tot * b[i] + c[i];}printf ( "%lld", result );return 0;
}

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

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

相关文章

CSP2021提高组复赛解析

前言 终于出成绩了我可以写博客辣&#xff0c;官方数据还没出就先放洛谷的题目链接了。 正题 T1-廊桥分配 https://www.luogu.com.cn/problem/P7913 题目大意 有m1m_1m1​种一类飞机&#xff0c;m2m_2m2​种二类飞机&#xff0c;每个飞机有一个占用时间的区间。要给两类飞机…

一起开心集训队第一周训练赛2021/3/14

文章目录比赛链接A CodeForces 1481D AB Graph题意&#xff1a;题解&#xff1a;代码&#xff1a;B CodeForces 1481E Sorting Books题意&#xff1a;题解&#xff1a;代码&#xff1a;C CodeForces 1478D Nezzar and Board题意&#xff1a;题解&#xff1a;代码&#xff1a;D …

使用Azure DevOps持续集成GitHub项目

点击蓝字关注我微软的Azure DevOps是一款软件开发管理工具&#xff0c;整合了需求、代码、编译、测试、发布等所有功能于一身。今天我们就来看看如何用Azure DevOps对自己GitHub上的项目做持续集成&#xff0c;并能在GitHub显示最新编译状态。其实在不久之前&#xff0c;Azure …

[BZOJ 3811]玛里苟斯(线性基)尽量理解的题解

文章目录titlesolutioncodetitle 魔法之龙玛里苟斯最近在为加基森拍卖师的削弱而感到伤心&#xff0c;于是他想了一道数学题。 S 是一个可重集合&#xff0c;S{a1,a2,…,an}。 等概率随机取 S 的一个子集 A{ai1,…,aim}。 计算出 A 中所有元素异或和&#xff0c;记为 x, 求 x^…

CF464E The Classic Problem(线段树 最短路)

CF464E The Classic Problem \(\bigstar\texttt{Hint}\)&#xff1a;发现没有什么好的突破口&#xff1f;为什么不想想怎样才能实现题目中 \(2^x\) 的加减法呢&#xff1f; 可见每次加减法&#xff0c;我们要做的是将添加的 \(1\) 和右边的连续的 \(1\) 合并为一整段&#xff0…

C. Longest Simple Cycle

C. Longest Simple Cycle 题意&#xff1a; 有n条链&#xff0c;第i条链上有c[i]个点&#xff0c;a[i]为第i条链的顶点与第i-1条链的连接点&#xff0c;b[i]为第i条链的最后一个点与第i-1条链的连接点。通过上面的方法连接链会产生很多的环&#xff0c;问这些环的最大长度。 …

【CF813F】Bipartite Checking(线段树分治+可删除并查集)

文章目录titlesolutioncodetitle You are given an undirected graph consisting of n vertices. Initially there are no edges in the graph. Also you are given q queries, each query either adds one undirected edge to the graph or removes it. After each query you…

在.Net Core WebAPI下给Swagger增加导出离线文档功能

一丶前言最近刚接触到Swagger&#xff0c;在github上下载了它的源码和demo学习了一遍&#xff0c;发现这个组件非常好用&#xff0c;不过不足的是它没有导出离线文档的功能&#xff0c;于是乎我就想给它加一个导出功能Swagger Github开源地址二丶思路其实说白了api文档就是一个…

YBTOJ洛谷P4331:数字序列(左偏树)

文章目录题目描述数据范围解析代码题目描述 数据范围 n<1e6n<1e6n<1e6 解析 先考虑简单情况 如果原数列是单调递增的&#xff0c;显然应该使biaib_ia_ibi​ai​ 如果单调递减&#xff0c;应该取中位数 那么原数列如果分成单调递减的几段&#xff0c;那么每一段都取中…

P8441 旭日东升(二维数点经典套路)

P8441 旭日东升 维护一个不可重集合的序列 \(a\)&#xff0c;长度为 \(n\)。支持以下两种操作&#xff1a; l r x 对于每个 \(l\le i\le r\)&#xff0c;将 \(x\) 并入 \(a_i\)。l r 设 \(S\) 把每个 \(l\le i\le r\) 的 \(a_i\) 并在一起的集合&#xff0c;输出 \(S\) 中所有元…

深搜、广搜、搜索剪枝

搜索与回溯讲解 文章目录深搜方向向量&#xff1a;DFS代码&#xff1a;题目讲解&#xff1a;八皇后问题字符序列自然数的拆分广搜BFS代码&#xff1a;题目讲解&#xff1a;瓷砖关系网络bfs与dfs的用途与区别搜索剪枝可行性剪枝最优性剪枝记忆化搜索搜索顺序剪枝题目&#xff1a…

使用logdashboard查看可视化日志

logdashboard日志面板是我在Github写的一个开源项目&#xff0c;旨在让查看日志变的方便快捷。在线预览现在功能有日志检索、趋势图、异常堆栈快速查看、日志详情等logdashboard支持自定义日志模型可以记录更多自定义的属性。logdashboard支持的日志来源有以下两种&#xff0c;…

数论分块专题复习(余数求和+模积和+Ice Rain+The Fool)

文章目录前提知识复习T1&#xff1a;余数求和titlesolutioncodeT2&#xff1a;Ice RaintitlesolutioncodeT3&#xff1a;The FooltitlesolutioncodeT4&#xff1a;模积和titlesolutioncode前提知识复习 整除分块是用于快速处理形似下列式子的方法&#xff0c;是解决莫比乌斯反…

领域驱动设计,让程序员心中有码(六)

领域驱动设计-聚合&#xff0c;一种极简的思维模式引言作为IT技术产业飞速发展的产物&#xff0c;软件工程学已经成为当今时代非常重要的一个学科。作为一名资深的软件开发从业者&#xff0c;我们需要学习的东西实际上已经远远超出了原本在大学教育阶段所接受的知识深度和广度&…

hdu 5094 Maze

题意&#xff1a; n*m大的迷宫 &#xff0c;有p种钥匙。钥匙最多有10种。 然后一个k&#xff0c;然后k行表示 (x1,y1),(x2,y2)直接有门或者墙。 如果g0 &#xff0c;就是有墙&#xff0c; 如果g>0 表示有门&#xff0c;且门需要第g把钥匙才能开。 然后下来一个s&#xff…

数论分块练习([CF830 C]Bamboo Partition + [hdu 6395]Sequence )

文章目录T1&#xff1a;SequencetitlesolutionT2&#xff1a;Bamboo PartitiontitlesolutioncodeT1&#xff1a;Sequence title 传送 solution 一眼就是很裸的矩阵加速 ⌊pl⌋\lfloor\frac{p}{l}\rfloor⌊lp​⌋分块矩阵加速就可以了 [BA1][DC⌊pl⌋010001]\begin{bmatrix}…

YBTOJ:染颜色(KDtree)

文章目录题目描述数据范围解析代码题目描述 数据范围 n≤105,T≤5n\le10^5,T\le5n≤105,T≤5 解析 关键是对问题的转化 考虑一次修改&#xff0c;一个点需要满足哪些条件才可以满足 1.与x的距离不超过lll 2.在x的子树内 这两个条件可以转化为对深度的限制和对dfs序的限制 这样…

Kubernetes初探[1]:部署你的第一个ASP.NET Core应用到k8s集群

Kubernetes简介Kubernetes是Google基于Borg开源的容器编排调度引擎&#xff0c;作为CNCF&#xff08;Cloud Native Computing Foundation&#xff09;最重要的组件之一&#xff0c;它的目标不仅仅是一个编排系统&#xff0c;而是提供一个规范&#xff0c;可以让你来描述集群的架…

01分数规划

参考文章 01分数规划 什么是01分数规划&#xff1a; 给定n个a[i]和b[i]&#xff0c;a[i]和b[i]绑定在一起要选同时选&#xff0c;求sum(a[i]) 除以 sum(b[i]) 的最大值&#xff0c;sum为求和函数 对于这种问题我们可以多定义一个数组x[1…n]&#xff0c;x为bool型只取0或者1,…

CF1156D 0-1-Tree(换根DP)

牛犇犇titlesolutioncodetitle 戳一戳 solution 直接设dp[i][k]dp[i][k]dp[i][k]表示以iii为根时&#xff0c;子树内&#xff0c;边权为kkk时的答案 &#xff08;定义写得好复杂&#xff0c;可略过&#xff09; 考虑对于点uuu&#xff0c;vvv是他的一个儿子&#xff0c;两点…