比赛链接内网:10.7.95.2
F题(原创):
传说在这片魔导大陆上有一位死神曾降下过神谕,如果谁能够解决其留下的这道问题,它就能保其永生!.给定一个长度为n的字符串S,试选择一段连续子串S[L~r],满足2<l<r<n且S[l~r]是字符串S的前缀,即S[L~r]与S[1~r-1+1]米相同。问能够选出的满足条件的连续子串的最长长度是多少?哦对,忘了说了,这片大陆现在是不死族的领地。
输入 仅一个由小写字母组成的字符串S。1<|S|< 500000。
输出 一个整数,表示最长长度。
样例输入
ababa
abcde
样例输出
3
0
题意:求出字符串最大的前缀,这个前缀在主串后面有和他相同的一段。
心得:一开始做这道题的时候题目看错了,直接误以为求最大前缀next的板子题,但实际上仔细一想这个思路是对的。(就是说无论那个相同的段在哪个地方,next都能遍历到)属于是瞎猫碰上死耗子了(哭哭)。
#include <bits/stdc++.h>
#define int long long
#define CIO std::ios::sync_with_stdio(false)
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define nep(i, r, l) for (int i = r; i >= l; i--)
using namespace std;
const int N=2e6+5;
char s[N];
int nxt[N];
int ma=-1;
void next(){
int i=0,j=-1;
nxt[0]=-1;
while (i<strlen(s)){
if (j==-1||s[i]==s[j]){
i++;j++;
nxt[i]=j;
ma=max(j,ma);
}
else{
j=nxt[j];
}
}
}
void work(){
cin>>s;
next();
cout<<ma;
}
signed main(){
CIO;
work();
return 0;
}
PS:学长说还能用字符串哈希+二分,或者后缀数组做。(这两个都还没学过)
E题:blocks
洛谷P8185
为了提高她的词汇量,奶牛 Bessie 拿来了一套共四块积木,每块积木都是一个正方体,六面各写着一个字母。她正在将积木排成一排,使积木顶部的字母拼出单词,以此来学习拼写。给定Bessie 四块积木上的字母,以及她想要拼写的单词列表,请判断她可以使用积木成功拼写列表中的哪些单词。
输入 第一行包含 N(1≤N≤10),为 Bessie 想要拼写的单词数。以下四行,每行包含一个包含六个大写字母的字符串,表示 Bessie 的一块积木六面上的字母。以下 N 行包含 Bessie 想要拼写的 N 个单词。每一个均由 1 到 4 个大写字母组成。
输出:"YES" or "NO"
样例输入
6
MOOOOO
OOOOOO
ABCDEF
UVWXYZ
COW
MOO
ZOO
MOVE
CODE
FARM
样例输出
YES
NO
YES
YES
NO
NO
题意:四个六面骰子每面都有一个字母,q次询问,能不能拼成对应单词
心得:做的时候卡了好久一直在模拟,又存桶,又记忆的,最后用纯暴力过,代码很长,正解应该是搜索,自己搜索掌握得不是很好。
自己的代码
#include <bits/stdc++.h>
#define int long long
#define CIO std::ios::sync_with_stdio(false)
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define nep(i, r, l) for (int i = r; i >= l; i--)
using namespace std;
const int N=2e6+5;
struct ss{
char c[10];
}s[15];
int tong[10];
int t[10][10];
char w[10];
void work(){
int n;cin>>n;
rep(i,1,4){
rep(j,1,6){
cin>>s[i].c[j];
}
}
rep(i,1,n){
cin>>w;
int len=strlen(w);
memset(t,0,sizeof t);
rep(j,0,len-1){
rep(k,1,4){
rep(l,1,6){
if (s[k].c[l]==w[j]){
t[k][j+1]=1;
break;
}
}
}
}
int f=0;
rep(a,1,len){
rep(b,1,len){
rep(c,1,len){
rep(d,1,len){
int ans=0;
memset(tong,0,sizeof tong);
tong[a]=1;tong[b]=1;tong[c]=1;tong[d]=1;
rep(j,1,len){
ans+=tong[j];
}
if (ans<len){
continue;
}
if (t[1][a]+t[2][b]+t[3][c]+t[4][d]>=len&&f==0){
cout<<"YES"<<endl;
f=1;
}
}
}
}
}
if (f==0){
cout<<"NO"<<endl;
}
}
}
signed main(){
CIO;
work();
return 0;
}
scanf("%s",s+1)可以让s字符串从1开始读。
H题:Sleeping in Class
洛谷P8183
题意:给你一个数组,你可以将这个数组中的相邻两个数替换为它们的和,设这样为 1 次操作,则进行多少次操作后,数组中所有的数相等。
输入
3 6 1 2 3 1 1 1 3 2 2 3 5 0 0 0 0 0
输出
3 2 0
心得:二分,这样子用的二分题目有好多,思路核心是想到用二分(doge),本质是根据二分确定答案,再验证答案成不成立。
#include <bits/stdc++.h>
#define int long long
#define CIO std::ios::sync_with_stdio(false)
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define nep(i, r, l) for (int i = r; i >= l; i--)
using namespace std;
const int N=2e5+5;
int a[N];
int sum;
int n;
int check(int x){
if (sum%x!=0)
return false;
int av=sum/x;
int ans=0,i=0;
while (i<=n){
ans=0;
while (ans<av&&i<=n){
i++;
ans+=a[i];
}
if (ans>av){
return false;
}
}
return true;
}
void work(){
cin>>n;
sum=0;
rep(i,1,n){
cin>>a[i];
sum+=a[i];
}
if (sum==0){
cout<<0<<endl;
return;
}
nep(i,n,1){
if (check(i)==true){
cout<<n-i<<endl;
break;
}
}
}
signed main(){
CIO;
int _;cin>>_;
while (_--){
work();
}
return 0;
}
J题:Photoshoot 2
洛谷P8184
题目描述
在一个似曾相识的场景中, Farmer John正在将他的N头奶牛(1<N<105)排成一排(为了方便将它们按1…N编号),以便拍照。最初,奶牛从左到右按照a1, a2,...,aN的顺序排列。Farmer John的目标是按照b1,,bN从左到右的顺序排列奶牛。为此,他可以对排列顺序进行一系列修改。每次修改为选择一头奶牛并将其向左移动一些位置。请计算农民约翰按所需顺序排列奶牛所需的最少修改次数。
输入格式
输入的第一行包含N,第二行包含a1, a2,….,aN,第三行包含b1, b2,,bN
输出格式
输出产生Farmer John所需顺序所需的最少修改次数。
输入
5 5 1 3 2 4 4 5 2 1 3
输出
2
题意:给两个数组,数组1的元素可以往左移动任意格,最少移动行为,使得两数组相等。
心得:第一次在实战中结合到了差分数组,过的时候还不敢相信,就是突然写完就过了。
因为移动格子后,本来在左边的元素就右移,相当于一个区间加一。区间修改,单点查询,然后就想到了差分数组。
#include <bits/stdc++.h>
#define int long long
#define CIO std::ios::sync_with_stdio(false)
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define nep(i, r, l) for (int i = r; i >= l; i--)
using namespace std;
const int N=2e5+5;
int a[N],b[N],af[N];
int d[N];
int n;
int lowbit(int x){
return x&(-x);
}
void add(int x,int b){
while (x<=n){
d[x]+=b;
x+=lowbit(x);
}
}
int query(int x){
int ans=0;
while (x){
ans+=d[x];
x-=lowbit(x);
}
return ans;
}
void work(){
cin>>n;
rep(i,1,n){
cin>>a[i];
af[a[i]]=i;
}
rep(i,1,n)
cin>>b[i];
int cnt=0;
rep(i,1,n){
if (af[b[i]]+query(af[b[i]])!=i){
add(1,1);
add(af[b[i]],-1);
cnt++;
}
}
cout<<cnt;
}
signed main(){
CIO;
work();
return 0;
}
上面是考试做出的四道题。
补题可以补:
K:Reincarnated MOO 一道原创题,思路和F的一种做法一样,字符串哈希+二分
I:Photoshoot 思维题,偶数看成一段变成01数组
L:Visits 和图有无环有关
A:Subset Equality 字符串难题。(思路也没懂)
B:Redistributing Gifts 巧解可以变成Floyd图解。(样例给到500可以联想n^3复杂度)