// 1 小美的用户名:
#include
#include
using namespace std;
/*
input:
第一行包含一个正整数T,表示需要检验的用户名数量
接下来有T行,每行一个不超过20的字符串s,表示输入的用户名
output:
对于每一个输入的用户名s,请输出一行(Wrong or Accept);
Accept:
1.用户名的首字符必须是大写或者小写字母
2.用户名只能包含大小写字母,数字
3.用户名需要包含至少一个字母和一个数字
*/
namespace test01{
class UserName{
public:
int judgeUN(void){
int num;
cin>>num;
while(num--){
bool flag = false;
string str;
cin>>str;
int len = str.size();
for(int i = 0; i < len; i++){
char c = str[i];
bool isLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
bool isDigit = c >= '0' && c <= '9';
if (i == 0 && !isLetter) break;
if (i != 0 && isDigit) flag = true;
if (i != 0 && !isLetter && !isDigit) {
flag = false;
break;
}
}
if(flag){
cout<<"Accept"<<endl;
}
else{
cout<<"Wrong"<<endl;
}
}
return 0;
}
};
}
// 2 小美的仓库整理:
#include
#include
#include
/*
输入:
第一行包含一个正整数n,表示货物的数量
第二行包含n个正整数,表示1-n号货物的重量w_i
第三行有n个数,表示小美按顺序取出的货物的编号,也就是一个1-n的全排列
输出:
包括n行,每行一个整数,表示每取出一件货物以后,对于重量和最大的一堆货物,其重量和为多少
input:
5
3 2 4 4 5 nums数组
4 3 5 2 1 perm数组(0 1 4 2 3)
output: ans数组
9
5
5
3
0
*/
// 解题思路:思想就是将删除过程视为插入过程的逆过程,同时以一些方法维护插入过程的最大区间和
// 逆序4 3 5 2 1 -> 1 2 5 3 4,表示插入元素的位置顺序,并维护一个最大连续和
namespace test02{
class storeManage{
public:
void ManageStore(){
int n;
cin >> n;
vector<int> nums(n);
for(int i = 0; i < n; i++){
cin >> nums[i];
}
vector<int> perm(n+1);
for(int i = n; i >= 1; i--){
cin >> perm[i];
perm[i] -- ; // 将排列从{1:n}转变到{0:n-1} { 0 1 4 2 3 }
}
unordered_map<int, int> mark; // 记录连续区间的另一头
unordered_map<int, int> sum; // 记录连续区间的和
vector<int> ans(n+1);
ans[0] = 0;
for(int i = 1; i <= n; i++){
int v = perm[i]; // 插入的位置
mark[v] = v; // 刚插入的时候,v的左右边界都是他本身,直接赋值即可
sum[v] = nums[v]; // 刚插入的时候,v所在的连续序列和就是他本身
ans[i] = max(ans[i-1], sum[v]); // 更新结果集
for(auto u : {v - 1, v + 1}){ // 遍历左右,看是否存在已经插入的邻居
auto it = mark.find(u);
if(it != mark.end()){ // 如果i+1的邻居已经存在于表中
int x = mark[v], y = mark[u]; // 用x代表v的另一端位置, 用y代表v+i的另一端位置
mark[x] = y;
mark[y] = x; // 两个端点分别记录位置
sum[x] = sum[y] = sum[x] + sum[y]; // 维护sum数组, 由于是求sum 直接求和即可
ans[i] = max(ans[i-1], sum[x]); // 维护答案
}
}
}
for(int i = n - 1; i >= 0; i--){ // 逆序输出答案
cout<<ans[i];
}
}
};
}
#include
#include
#include
using namespace std;
// 3 小美的跑腿代购:
/*
input:
输入第一行包含两个正整数n,m,表示订单的数量和小美可以接的订单数量(1<=n,m<=10000)
接下来有n行,第i行表示i-1号订单的信息。每行有两个正整数v和w,表示一个订单的跑腿价格和商品重量
output:
输出包含m个1~n之间的正整数,中间用空格隔开,表示选择的订单编号
*/
namespace test03{
typedef struct Node{
int id; //订单编号
int value;
Node() {}
Node(int id, int v, int w){
this->id = id;
value = v + (w*2);
}
}node;
// 按照value的值由大到小进行排序,当value的值相同时,按照id由小到大排序
bool cmp(node x, node y){
if(x.value == y.value){
return x.id < y.id;
}else{
return x.value > y.value;
}
}
int main(){
int n,m;
cin>>n>>m;
// 最好使用n初始化goods数组,
vector<node> goods(n);
int v = 0;
int w = 0;
for(int i = 0; i < n; i++){
cin >> v >> w;
goods[i] = Node(i+1, v, w);
}
sort(goods.begin(), goods.end(), cmp); // 当前的goods[i].id符合结果集,但是不是按照id由小到大的顺序排序
// 选取前m个goods,将其按照id的由小到大的顺序排序
priority_queue<int, vector<int>, greater<int>> que;
for(int i = 0; i < m; i++){
que.push(goods[i].id); // 按照goods[i].id由大到小进入que;
}
for(int i = 0; i < m; i++){
cout<<que.top()<<" ";
que.pop();
}
}
// 关于优先级队列的使用:
// 默认情况下使用less即大顶堆(由大到小排序),当使用greater即小顶堆(由小到大排序)
// 定义: priority_queue
// Type: 数据类型
// Container: 容器类型(Container必须是用数组实现的容器,比如vector、deque等等STL里面默认用的是vector)
// Functional: 比较的方式(默认less)
}
// 4 小团的复制粘贴:
/*
input:
第一行包含一个正整数n,表示序列A和序列B的长度
第二行包含n个正整数,表示序列A中的n个元素,第i个数字表示下标为i的位置上的元素
第三行是一个操作数m,表示进行的操作数量
每一步操作:
粘贴操作:1 k x y 将A序列从下标x位置开始,连续k个元素粘贴到B序列中从下标y开始的连续k个位置
查询操作:2 x 查询B序列下标x处的值
eg: 1 2 3 4 A:3 B:4 连续两个 B4 == A3 B5 == A4
1 进行操作 2 进行输出
output:
对于每一个操作2输出一行,每行仅包含一个正整数,表示针对某一个询问的答案
*/
// 方法1:使用有序容器记录所有的复制粘贴操作,一旦遇到查询操作,就从后往前搜索,查询哪次粘贴操作将覆盖到
// 本次查询的位置;假设本次查询的位置为pos,从后往前搜索粘贴操作,if pos between (y,y+k-1),即返回A[x+pos-y]
namespace test04{
int main(){
int n;
cin>>n;
vector<int> A(n);
vector<int> B(n,-1);
for(int i = 0; i < n; i++){
int num;
cin>>num;
A[i] = num;
}
int m;
cin>>m;
vector<int> vec(m);
int j = 0;
while(m>0){
int a;
cin>>a;
if(a == 1){
int k,x,y;
cin>>k>>x>>y;
while(k > 0){
B[y - 1] = A[x - 1];
y++;
x++;
k--;
}
}
if(a == 2){
int x;
cin>>x;
cout << B[x - 1] << endl; // 输出
}
m--;
}
return 0;
}
}
// 5 小美的区域会议:
/*
input:
第一行包含两个整数n和k,n表示区域的数量,k表示不能超过的级别
接下来有n-1行,每行有两个正整数a和b,表示a号区域和b号区域有一条边 (n个区域n-1条边)
最后一行有n个整数,第i个整数表示i号区域负责人的级别
output:
符合要求(召集的负责人所在的区域必须构成一个非空的连通的图,这些负责人中,级别最高的和级别最低的相差不超过k)的方案数
表示可以选择的方案数对10^9+7取模之后的结果
*/
#include
#include
#include
namespace test05{
long dfs(unordered_map<int,vector<int>> &tree, vector<bool> &visited, int i, vector<int> &vec, int k,int k0,int i0){
visited[i] = true;
long a = 1;
for(int j : tree[i]){
if(!visited[j] && vec[j] >= k0 && vec[j]-k0 <= k && (vec[j]>k0||j<i0)) //j号的级别高于i号的级别,j小于i
a = (a*(1+dfs(tree,visited,j,vec,k,k0,i0)))%1000000007;
}
return a;
}
int mian(){
int n,k;
cin>>n;
cin>>k;
unordered_map<int,vector<int>> tree(n);
for(int i = 0; i < n - 1; i++){
int a,b;
cin>>a>>b;
tree[a].push_back(b);
tree[b].push_back(a); //记录每个区域的相邻区域集
}
vector<int> vec(n);
for(int i = 0; i < n; i++){
int num;
cin>>num;
vec.push_back(num);
}
long ret;
for(int i = 0; i < n; i++){
vector<bool> visited(n);
long a = dfs(tree,visited,i,vec,k,vec[i],i);
ret = (ret + a)%1000000007;
}
cout<<ret<<endl;
return 0;
}
}
// 6 小团的神秘暗号
/*
input:
第一行是一个正整数n,表示加密后的字符串总长度
第二行是一个长度为n的仅由大写字母组成的字符串T
output:
仅包含一个符合要求的最长字符串S
*/
// 要求:头部字符串满足至少包含一个“MT”子序列,且以T结尾、尾部字符串需要满足至少包含一个“MT”子序列,且以M开头;
#include
#include
#include
namespace test06{
int main(){
int n;
cin>>n;
string str;
cin>>str;
string sstr;
int startpos,endpos;
int pos1 = str.find("M");
sstr = str.substr(pos1+1,str.size());
if(sstr.find("T")!= -1){
startpos = sstr.find("T");
}
sstr = sstr.substr(startpos+1,sstr.size());
int pos2 = sstr.rfind("T");
sstr = sstr.substr(0,pos2);
if(sstr.rfind("M")!= -1){
endpos = sstr.rfind("M");
}
sstr = sstr.substr(0,endpos);
cout<<sstr<<endl;
return 0;
}
}
// 7 小团的选调计划
/*
input:
第一行是一个正整数n,表示业务骨干和业务区域数量
接下来有n行,每行n个整数,即一个1~n的排列,第i行表示i-1号业务骨干的意向顺序
output:
包含n个正整数,第i个正整数表示第i号业务骨干最终去的业务区域编号
*/
#include
#include
using namespace std;
namespace test07
{
int main() {
int n;
cin >> n;
// 二维数组的初始化规则
vector<vector<int>> vec(n,vector<int>(n));
vector<int> res(n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> vec[i][j];
unordered_map<int, int> umap;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++) {
int num = vec[i][j];
if (!umap.count(num)) {
umap[num] = i;
res[i] = num;
break;
}
}
}
for (int i = 0; i < n; i++){
cout << res[i] << " ";
}
cout << endl;
return 0;
}
} // namespace test07
// 8 小团无路可逃
/*
1
2 3
4 5
n:5 x:1 y:2
1: 0 1 1 2 2
2: 1 0 2 1 3
input:
第一行包含三个整数n,x,y,分别表示树上的结点数量,小美所在的位置和小团所在的位置
接下来有n-1行,每行两个整数u,v,表示u号位置和v号位置之间有一条边,即u号位置和v号位置彼此相邻
output:
仅包含一个整数,表示小美追上小团所需的时间
*/
#include
#include
#include
namespace test08{
unordered_map<int,vector<int>> umap;
void dfs(int x, int y, vector<int> &trace){ //参数1表示起始结点 参数2表示可达结点 参数3记录从起始结点到当前结点的最短路径
trace[x] = trace[y] + 1; //起始结点即结点本身,距离为0
int len = umap[x].size(); //记录起始结点的周围结点
for(int i = 0; i < len; i++){
int z = umap[x][i]; //结点z即起始结点的其中一个周围结点
if(z == y) continue;
// trace[1] = 1;
// trace[3] = 2;
// trace[5] = 3;
// trace[4] = 1;
dfs(z,x,trace); //以结点2为起始结点,结点1与结点4为周围结点,从起始结点2到结点4的最短路径为1 dfs(4,2,trace) break
//从起始结点2到结点1的最短路径为1 dfs(1,2,trace)=1 dfs(3,2,trace)=2 dfs(5,2,trace)=3
}
}
int main(){
int n,x,y; //树上结点数量 小美->小团所在位置(1~n)
cin>>n>>x>>y;
for(int i = 0; i < n - 1; i++){ //umap[i]保存树上某一个结点[i]的周围结点vector
int u,v;
cin>>u>>v;
umap[u].push_back(v);
umap[v].push_back(u);
}
int ret = 0;
vector<int> trace_x(n+1); //结点x到达其余所有结点的最短路径[0]=-1
vector<int> trace_y(n+1); //结点y到达其余所有结点的最短路径[0]=-1
trace_x[0] = trace_y[0] = -1;
dfs(x,0,trace_x);
dfs(y,0,trace_y);
for(int i = 1; i <= n; i++){ //i=1~n
if(trace_y[i] < trace_x[i]){ //当结点y到达的某一个结点比结点x快时,才符合小美追逐小团的条件
ret = max(ret, trace_x[i]);
}
}
cout<<ret;
return 0;
}
}
// 9 小团的装饰品
/*
m个空位
a[1] a[2] ... a[m]
a[x]<=n 空位i,j上的装饰品的价格需要满足:a[i] <= a[j] && a[j]%a[i]=0 && a[i]<=n && a[j]<=n
cin>>m,n
input:
n和m(装饰品的最大价值 空位)
output:
一个数,结果对998244353取模,表示购买的方案数
*/
/*
动态规划,dp[i][j]表示第i个物品房价格为j的装饰品时有多少种方案
当我们在确定第i个装饰物时,其实它的价格是有限制的,如果第i-1个装饰物价格为j,那么第i个装饰物的价格只能是j的整数倍,且不能超过n。
而第i个装饰物对于任意确定的价格k=j*times,可能存在多组(j, times)乘积相同,把这些方案数全部加起来才能得到dp[i][k],因此状态转移方程为:
dp[i][j*times] = dp[i][j*times] + dp[i - 1][j] (times为整数,满足j*times<=n)
最后将第m个装饰物的所有价格的方案数加起来就是我们要求的方案总数
*/
namespace test09{
int main(){
int n,m;
cin>>n>>m;
const int mod = 998244353;
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
for(int i = 1; i <= n; i++){
dp[1][i] = 1;
}
for(int i = 2; i <= m; i++){ //第i个位置
for(int j = 1; j <= n; j++){ //第i个位置装饰品的价值 dp[i][j*times] = dp[i-1][j] + dp[i][j*times];
for(int k = 1; j*k <= n; k++){
dp[i][j*k] = (dp[i-1][j] + dp[i][k*j])%mod;
}
}
}
int ret = 0;
for (int i = 1; i <= n; ++i) {
ret = (ret + dp[m][i]) % mod;
}
cout<<ret;
return 0;
}
}
int main(){
// test01::UserName obj1;
// obj1.judgeUN();
test02::storeManage obj2;
obj2.ManageStore();
return 0;
}