点此前往练习
小团惹小美生气了,小美要去找小团“讲道理”。小团望风而逃,他们住的地方可以抽象成一棵有n个结点的树,小美位于x位置,小团位于y位置。小团和小美每个单位时间内都可以选择不动或者向相邻的位置转移,很显然最终小团会无路可逃,只能延缓一下被“讲道理”的时间,请问最多经过多少个单位时间后,小团会被追上。
输入描述:
输入第一行包含三个整数n,x,y,分别表示树上的结点数量,小美所在的位置和小团所在的位置。接下来有n-1行,每行两个整数u,v,表示u号位置和v号位置之间有一条边,即u号位置和v号位置彼此相邻。(1<=n<=50000)
输出描述:
输出仅包含一个整数,表示小美追上小团所需的时间。
输入例子1:
5 1 2
2 1
3 1
4 2
5 3
输出例子1:
2
思路:
使用深搜,分别以 x,y为起点搜索到所有其他点的路径长度,然后取dx > dy得到最大的dx。
Ref:参考文章
代码:
#include
using namespace std;
void dfs(vector<vector<int>>& tree, vector<int>& dis, int u, int fa, int step)
{
for(int v :tree[u])
{
if(v==fa) continue;
dis[v]=step+1;
dfs(tree,dis,v,u,step+1);
}
}
int main()
{
int n,x,y;
cin>>n>>x>>y;
vector<vector<int>> tree(n+1);
int out = 0;
for(int i = 1; i <= n-1; i++)
{
int u,v;
cin>>u>>v;
tree[u].push_back(v);
tree[v].push_back(u);
}
vector<int> disx(n+1, 0);
vector<int> disy(n+1, 0);
dfs(tree, disx, x, -1, 0);
dfs(tree, disy, y, -1, 0);
for(int i = 1; i <= n; i++)
{
if(disx[i]>disy[i])
out = max(out, disx[i]);
}
cout<<out;
return 0;
}
小团深谙保密工作的重要性,因此在某些明文的传输中会使用一种加密策略,小团如果需要传输一个字符串S,则他会为这个字符串添加一个头部字符串和一个尾部字符串。头部字符串满足至少包含一个“MT”子序列,且以T结尾。尾部字符串需要满足至少包含一个“MT”子序列,且以M开头。例如AAAMT和MAAAT都是一个合法的头部字符串,而MTAAA就不是合法的头部字符串。很显然这样的头尾字符串并不一定是唯一的,因此我们还有一个约束,就是S是满足头尾字符串合法的情况下的最长的字符串。
很显然这样的加密策略是支持解码的,给出你一个加密后的字符串,请你找出中间被加密的字符串S。
输入描述:
输入第一行是一个正整数n,表示加密后的字符串总长度。(1<=n<=100000)输入第二行是一个长度为n的仅由大写字母组成的字符串T。
输出描述:
输出仅包含一个字符串S。
输入例子1:
10
MMATSATMMT
输出例子1:
SATM
思路:
使用贪心的想法,找最短的前后缀,即正向找到一次MT,反向找到一次TM。
Ref:参考文章
代码:
#include
using namespace std;
int main()
{
int n;
cin>>n;
string s;
cin>>s;
bool m=false,t=false;
int i,j;
for(i=0;i<s.length();i++)
{
if(s[i]=='M'&&!m)
m=true;
else if(s[i]=='T'&&m)
{
i++;
break;
}
}
for(j=s.length()-1;j>=0;j--)
{
if(s[j]=='T'&&!t)
t=true;
else if(s[j]=='M'&&t)
break;
}
cout<<s.substr(i,j-i);
return 0;
}
美团打算选调n名业务骨干到n个不同的业务区域,本着能者优先的原则,公司将这n个人按照业务能力从高到底编号为1 ~ n。编号靠前的人具有优先选择的权力,每一个人都会填写一个意向,这个意向是一个1~n的排列,表示一个人希望的去的业务区域顺序,如果有两个人同时希望去某一个业务区域则优先满足编号小的人,每个人最终只能去一个业务区域。
例如3个人的意向顺序都是1 2 3,则第一个人去1号区域,第二个人由于1号区域被选择了,所以只能选择2号区域,同理第三个人只能选择3号区域。
最终请你输出每个人最终去的区域。
输入描述:
输入第一行是一个正整数n,表示业务骨干和业务区域数量。(n≤300)接下来有n行,每行n个整数,即一个1~n的排列,第i行表示i-1号业务骨干的意向顺序。
输出描述:
输出包含n个正整数,第i个正整数表示第i号业务骨干最终去的业务区域编号。
输入例子1:
5
1 5 3 4 2
2 3 5 4 1
5 4 1 2 3
1 2 5 4 3
1 4 5 2 3
输出例子1:
1 2 5 4 3
思路:
使用一个bool数组来记录心仪的业务区域是否被选择了,如果被选择,则跳过;否则选择。
代码:
#include
#define N 310
using namespace std;
int main()
{
int n;
cin>>n;
int num[N][N];
bool s[N];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>num[i][j];
}
}
for(int i=0;i<n;i++)
{
int j=0;
while(s[num[i][j]])
j++;
s[num[i][j]]=1;
cout<<num[i][j]<<" ";
}
return 0;
}
小团从某不知名论坛上突然得到了一个测试默契度的游戏,想和小美玩一次来检验两人的默契程度。游戏规则十分简单,首先有给出一个长度为n的序列,最大值不超过m。
小团和小美各自选择一个[1,m]之间的整数,设小美选择的是l,小团选择的是r,我们认为两个人是默契的需要满足以下条件:
l小于等于r。
对于序列中的元素x,如果0
小团为了表现出与小美最大的默契,因此事先做了功课,他想知道能够使得两人默契的二元组
我们称一个序列A为单调不下降的,当且仅当对于任意的i>j,满足Ai>=Aj。
输入描述:
输入第一行包含两个正整数m和n,表示序列元素的最大值和序列的长度。(1<=n,m<=100000)输入第二行包含n个正整数,表示该序列。
输出描述:
输出仅包含一个整数,表示能使得两人默契的二元组数量。
输入例子1:
5 5
4 1 4 1 2
输出例子1:
10
思路:
Ref:参考评论区
代码:
#include
using namespace std;
int solve(vector<int> &nums, int m) {
int cnt = 0, n = nums.size();
for (int r = m; r > 0; --r) {
// 枚举 l 的最大可能性
int lo = 0, hi = r, mid; // [0, r],0是为了方便判断 (r,m+1) 所选序列是非法的
while (lo < hi) {
mid = (hi - lo + 1) / 2 + lo;
// 在 nums 中选出 (0, l) ∪ (r, m+1) 的元素并检测是否单调非降
int pre = -1, flag = 1; // nums[i] > 0
for (int x: nums) {
if (x < mid || x > r) {
if (x < pre) {
flag = 0;
break;
}
pre = x;
}
}
if (flag) { // 尝试把 l 放大的同时记录答案
lo = mid;
} else { // 一定不是,那么把 l 减小
hi = mid - 1;
}
}
// 如果 lo = 0,证明不管怎么降低 l 都无法构成单调非降,因为 (r,m+1) 所选的子序列有问题
if (0 == lo) break;
cnt += lo;
}
return cnt;
}
int main() {
int m, n; cin >> m >> n;
vector<int> nums(n);
for (int i = 0; i < n; ++i) {
scanf("%d", &nums[i]);
}
cout << solve(nums, m) << endl;
return 0;
}
第一题:
深度优先搜索(DFS)和广度优先搜索(BFS)
区别:
优缺点:
深搜(DFS) | 广搜(BFS) | |
---|---|---|
优点 | (1)能找出所有解决方案;(2)内存需求相对较少。 | (1)有效解决最短路径问题,寻找深度小;(2)每个结点只访问一遍。 |
缺点 | (1)多次遍历;(2)深度大时效率低。 | 内存消耗较大。 |
第二题:
string
类:
#include
string
对象:string s;
s.insert(pos,str);
pos是要插入的下标,str表示要插入的字符串。s.erase(pos,len);
pos是要删除的子字符串的起始下标,len表示要删除子字符串的长度。s.substr(pos,len);
pos 是要提取的子字符串的起始下标,len 为要提取的子字符串的长度。s.find(str,pos);
str表示要查找的字符串,pos为开始查找的下标,如果不指明,则从第0个字符开始查找。s.rfind(str,pos);
str表示要查找的字符串,pos为最多查找到的下标,如果到了pos所指定的下标还没有找到字符串,则返回一个无穷大值4294967295。s.find_first_of(str);
用于查找子字符串str和字符串s共同具有的字符在字符串中首次出现的位置。第三题:
暂无。