目录
- 涵盖知识点:思维、构造、马拉车。
- 比赛链接:传送门
- D题只有数据范围的区别,故只写D2。
- 好多题啊,随缘更新。
(其实懒得写)
- A - Bad Ugly Numbers
- B - Maximums
- C - Permutation Partitions
- D2 - Prefix-Suffix Palindrome (Hard version)
- 比赛链接:传送门
涵盖知识点:思维、构造、马拉车。
比赛链接:传送门
D题只有数据范围的区别,故只写D2。
好多题啊,随缘更新。(其实懒得写)
A - Bad Ugly Numbers
题意: 构造一个长度为\(n\)的数字使得其不能被其中的每一位数整除。
题解: 2333333(雾)
Accept Code:
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
if(n==1){
cout<<"-1\n";
continue;
}
else{
cout<<2;
for(int i=1;i<n;i++)cout<<3;
cout<<"\n";
}
}
return 0;
}
B - Maximums
题意: 对于数组\(a\),数组\(x\)满足\(x_i = max(0, a_1, \ldots, a_{i-1}),x_1=0\),数组\(b\)满足\(b_i = a_i - x_i\)。现在给定\(b\),要求反推\(a\)。
题解: 顺着算一遍维护一下最大值加一下就好了。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
ll a[maxn];
int main(){
int n;
cin>>n;
ll x=0;
for(int i=0;i<n;i++){
cin>>a[i];
a[i]+=x;
x=max(x,a[i]);
cout<<a[i]<<" ";
}
return 0;
}
C - Permutation Partitions
题意: 给定一种\([1,n]\)的排列,现在让你分成\(k\)块,求每块的最大值之和。形式上为\(\sum\limits_{i=1}^{k} {\max\limits_{l_i \leq j \leq r_i} {p_j}}\),并算出有多少种分法可以达到这个最大值。
题解: 最大值就是\([n-k+1,n]\)的区间和。根据这\(k\)个数来划分区间即可,记录这\(k\)个数的下标,分法总数为\(\displaystyle\prod_{i=1}^{k-1}(idx_{i+1}-idx_{i})\)。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10,mod=998244353;
typedef long long ll;
int main(){
int n,k;
cin>>n>>k;
ll ans=1,sum=0,l=0;
for(int i=1,p;i<=n;i++){
cin>>p;
if(p>n-k){
sum+=p;
if(l)
ans=ans*(i-l)%mod;
l=i;
}
}
cout<<sum<<" "<<ans<<"\n";
return 0;
}
D2 - Prefix-Suffix Palindrome (Hard version)
题意: 给定串\(s\),从\(s\)的前缀和后缀取任意长度进行拼接成新串\(t\),使得\(t\)为回文串并尽可能长。
题解: 先双端扫描一遍,确定回文的前缀和后缀,获得左区间和右区间。然后再依次扫描每一个字母为中心的回文串,若回文串左端探入左区间或者右端探入右区间,判断并更新答案。D1可以应该可以暴力判回文,D2利用马拉车获得的\(len\)数组优化计算一下就可以了。具体计算看代码实现。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
string s,t;
int len[maxn<<1];
void manacher(){
int center,right=0,radius;
for(int i=1;i<t.length()-1;i++){
if(i>=right)radius=1;
else radius=min(right-i+1,len[center*2-i]);
while(t[i+radius]==t[i-radius])radius++;
if(i+radius-1>right)right=i+radius-1,center=i;
len[i]=radius;
}
}
int main(){
int cas;
cin>>cas;
while(cas--){
cin>>s;
t="@#";
for(char i:s){
t+=i;
t+='#';
}
t+='$';
manacher();
int l=0;
while(l<s.length()&&s[l]==s[s.length()-l-1])l++;
if(l>=s.length()){
cout<<s<<"\n";
continue;
}
int anslen=0,ansl=0,ansr=0;
for(int i=2;i<=t.length()-3;i++){
int pl=(i-len[i])>>1,pr=(i+len[i]-4)>>1;
//cout<<pl<<" "<<pr<<"\n";
if(pl>pr)continue;
if(pl<=l){
int nl=pr,nr=s.length()-pl;
//cout<<"1:"<<nl<<" "<<nr<<"\n";
if(nl+1+s.length()-pl>=anslen&&nl<nr)
anslen=nl+1+s.length()-nr,ansl=nl,ansr=nr;
}
if(pr>=s.length()-l-1){
int nr=pl,nl=s.length()-pr-2;
//cout<<"2:"<<nl<<" "<<nr<<"\n";
if(nl+1+s.length()-nr>=anslen&&nl<nr)
anslen=nl+1+s.length()-nr,ansl=nl,ansr=nr;
}
}
//cout<<ansl<<" "<<ansr<<"\n";
string ans=s.substr(0,ansl+1)+s.substr(ansr);
cout<<ans<<"\n";
}
return 0;
}
原文地址:https://www.cnblogs.com/charles1999/p/12531391.html