S14754 赵廷赫
一,比赛情况
爆0。
二,补题报告
T1:
复读机(repeater)
时间限制:1秒 内存限制:256M
题目描述:
人类的本质是复读机。
小可喜欢在群里复读别人说过的话,这种人通常被称为复读机。现在小可想模拟复读机过程,过程如下:
现在给定一个长度为 n 的仅包含小写字母和数字的字符串,字母表示需要复读的消息,数字表示要复读的次数。
然而复读没有这么简单,小可想进行一个更复杂的复读模拟, 于是这个字符串中可能包含多个数字, 当多次出现数字时,例如 a5b2a5b2,我们从左到右解析这个字符串,a5a5 表示将 aa 复读 5 遍,即原字符串变 为 aaaaabaaaaab ,然后遇到数字 2 ,再将所有消息全部复读 2 遍,即 aaaaabaaaaab
题目解析:
模拟算法,模拟复读过程。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int t,n;
string s;
char a[500005];
int main()
{
freopen("repeater.in","r",stdin);
freopen("repeater.out","w",stdout);
cin>>t;
while(t--)
{
int cnt=0;
cin>>n>>s;
for(int i=0;i<n;++i)
{
if(s[i]>='a'&&s[i]<='z')
{
cnt++;
a[cnt]=s[i];
}
if(s[i]>='1'&&s[i]<='9')
{
int sum=0;
int k=i;
while(s[k]>='0'&&s[k]<='9')
{
sum=sum*10+(s[k]-48);
k++;
}
int maxn=0;
for(int p=2;p<=sum;++p)
{
for(int i=1;i<=cnt;++i)
{ maxn=max(maxn,(p-1)*cnt+i);
a[(p-1)*cnt+i]=a[i];
}
}
cnt=max(cnt,maxn);
}
}
for(int i=1;i<=cnt;++i)
{
cout<<a[i];
}
cout<<"\n";
}
return 0;
}
T2:
题目描述
有n个小可战士站成一排,他们的编号从1到n,每个小可都有一个战斗力xi=i,但是小可们有不同的分工,有的充当队伍的矛,有的充当队伍的盾,矛的攻击力和盾的防御力和小可本身的战斗力相同。我们要将小可们分成两个阵营,编号 [1,pos] 为第一阵营,第一阵营中我们只考虑矛的攻击力总和w,编号[pos+1,n]为第二阵营,第二阵营中我们只考虑盾的防御力总和v,请问对于所有的 pos ,∣w−v∣ 的值最小,请问∣w−v∣ 最小为多少。
输入描述
第一行:输入一个正整数 n 。
第二行:输入一行长度为 n 的只含有 0 或 1 的字符串,如果字符串某一位是0,则表示小可充当队伍矛,否则为盾。
输出描述
输出一个整数答案
题目解析:用前缀和和后缀和,枚举最小值,判断最小的绝对值。
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,a[100005],b[100005];
string s;
int main(){
cin>>n>>s;
s="*"+s;
for(int i=1;i<=n;++i){
if(s[i]=='1'){
a[i]=a[i-1];
}
else{
a[i]=a[i-1]+i;
}
}
for(int i=n;i>=1;--i){
if(s[i]=='1'){
b[i]=b[i+1]+i;
}
else{
b[i]=b[i+1];
}
}
ll minn=min(a[n],b[1]);
for(int i=1;i<=n;++i){
ll k=abs(a[i]-b[i+1]);
minn=min(minn,k);
}
cout<<minn;
return 0;
}
T3:
(illegality.cpp/c)
不合法字符串
3.1 问题描述
小可是一名小说审核员,他的工作是看小说,然后把小说中不合法字符串和谐掉。
现在给出若干个不合法的字符串 ,和一篇小说 ,小可需要把 中的不合法字符串用 * 和谐掉。当然小可是一个很聪明的审核员,他会用最少的 * 和谐字符串。
比如:
有三个不合法字符串: abc 、 ab 、 a 。 str=abcd
他会只和谐 a ,使得 str=*bcd ,这样小说中就没了不合法字符串。
请输出和谐之后的小说。
3.2 输入格式
第一行:输入一个整数 表示测试用例数。
对于每组测试样例:
第一行:输入一个正整数 n ,表示不合法字符串的数量。
接下来n行:每行输入一个字符串,表示不合法字符串。
接下来一行:输入一个字符串,表示小说。
3.3 输出格式
输出和谐之后的小说。
题目解析:
用枚举法,对每一位向前寻找,找到以这一位结尾的单词,则更改单词的最后一位。
AC代码:#include<bits/stdc++.h>
using namespace std;
int T,n,m;
string str[100000],tgt;
int main()
{
cin>>T;
while(T--){
cin>>m;
for(int i=1;i<=m;i++)
cin>>str[i];
cin>>tgt;
n=tgt.length();
tgt=' '+tgt;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i<str[j].length())
continue;
if(tgt.substr(i-str[j].length()+1,str[j].length())==str[j]){
tgt[i]='*';
}
}
}
for(int i=1;i<=n;i++)
cout<<tgt[i];
cout<<endl;
}
return 0;
}
T4:
虚假的珂朵莉树(kodori)
小可有一棵树,有 n 个节点,根节点为 1, 每个节点都有一个权值。
设每个节点与根节点距离是这个节点的深度。
小可会在这棵树上增加 m 条虚假边,任意一条虚假边不会和原来的树边或其他虚假边重合(增加的虚假边不影响节点深度)。
之后小可会进行 q 次操作:
操作1: 让结点 u 的权值增加 k ,并对与结点 u 相邻的结点中,深度比结点 k 小的结点重复操作1。 操作2:让结点 u 的权值增加 k ,并对与结点 u 相邻的结点中,深度比结点 u 大的结点重复操作2。
小可想知道,经过 q 次操作之后,所有的节点的权值是多少。
4.2 输入格式
第一行:输入三个整数 n、m、q,表示节点个数。虚假边条数,操作次数。
第二行:输入n个整数 ,表示节点的权值。
接下来 n-1 行:每行输入两个整数 u、v,表示树结构。
接下来 m 行:每行输入两个整数 u、v,表示虚假边。
接下来 q 行:每行输入三个整数 t、u、k。t表示操作类型、u表示要操作的节点,k表示权值增加k。
题目分析:
AC代码:
#include<bits/stdc++.h>
#define pr pair<int,int>
#define mk make_pair
using namespace std;
const long long p=1e9+7;
struct node{
int to,next;
}e[5000005];
vector<pr> g;
long long a[1000005],up[1000005],down[1000005];
int n,m,q,cnt,head[1000005],d[1000005];
void add(int u,int v){
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void dfs(int u,int fa){
g.push_back(mk(d[u],u));
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa) continue;
d[v]=d[u]+1;
dfs(v,u);
}
}
int main(){
cin>>n>>m>>q;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
add(u,v);
}
dfs(1,1);
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
for(int i=1;i<=q;i++){
int pd,u,v;
cin>>pd>>u>>v;
if(pd==1) up[u]=(up[u]+v)%p;
else down[u]=(down[u]+v)%p;
}
sort(g.begin(),g.end());
int x=g[i].second;
for(int j=head[x];j;j=e[j].next){
int y=e[j].to;
if(d[y]>d[x]) down[y]=(down[y]+down[x])%p;
}
}
reverse(g.begin(),g.end());
int x=g[i].second;
for(int j=head[x];j;j=e[j].next){
int y=e[j].to;
if(d[y]<d[x]) up[y]=(up[y]+up[x])%p;
}
}
for(int i=1;i<=n;i++) cout<<(a[i]+up[i]+down[i])%p<<" ";
return 0;
}