传送门
一下题解均是大概思路
Problem A
这个题写出来仅仅是带偏你的思路,本质上这题就是:给你种数字,拼凑,使得他们的乘积和在区间范围之内。
考虑爆搜,不断的对每种数进行搜索,如果发现当前数的乘积在范围内,则直接累计答案,而倘若当前的乘积大于则证明之后的所有情况均不可能,故直接剪掉即可。
事实证明,这样的爆搜非常的快!
Problem B
Problem C
考虑贪心。我们优先考虑一个管的情况。
要使得字典序最大,一种显然的方法就是,先取两边最大的。而如果两边的大小相同,则我们直接向中间收缩,直到找到两边大小不相同的的位置。此时我们只需要优先选取较大的位置即可。而这个过程可以用双指针来维护。
最后我们可以对两个管分开处理,分别求出两个管的最优情况,最后用将这两个种最优解连接,再做一次上述过程即为最终答案。
Problem D
Problem E
原题
Problem F
Problem G
Problem H
原题
在这题中甚至没有查询,连分块都不用了。
然后没有做出来
Problem I
原题
2018 牛客网暑期ACM多校训练营(第二场)D题。
原封不动的原题,只需要知道在最低点买入,最高点卖出即可。
Problem J
Problem K
原题
的弱化版,只需要将那题的改为即可通过
分析:
我们发现,在这个题中,询问非常多,字符串的长度并不是非常的大。因此我们可以考虑先把答案预处理出来。
因为涉及两个串的子串个数问题,因此我们不妨考虑使用后缀自动机预处理。
我们对其中一个串建立后缀自动机,我们用拓扑排序自底向上的对整个自动机的集合的大小进行更新(因为对于某个结点,他沿着后缀连接走到的结点必然是结点的后缀,故结点的答案必定要更新到结点)。
更新完集合的大小后,我们需要维护一个前缀和,代表到达当前结点时,终止点在的所有子串中,在串中出现的次数。
完成上述工作之后,我们只需要把串丢到后缀自动机上去匹配,每次去统计答案并记录下来供次询问查询即可。
整体时间复杂度:
代码:
#include <bits/stdc++.h>
#define maxn 4005
using namespace std;
char str[maxn];
typedef unsigned long long ll;
struct SAM{
int next[maxn*2][26],fa[maxn*2],len[maxn*2],last,cnt=0;
ll cntA[maxn*2],A[maxn*2];
ll num[maxn*2],sum[maxn*2];
SAM(){clear();}
void clear(){
last=cnt=1;
memset(sum,0,sizeof(sum));
memset(num,0,sizeof(num));
memset(next[1],0,sizeof(next[1]));
memset(len,0,sizeof(len));
fa[1]=len[1]=0;
}
void Insert(int c){
int p=last;
int np=++cnt;
num[np]=1;
memset(next[cnt],0,sizeof(next[cnt]));
len[np]=len[p]+1;last=np;
while(p&&!next[p][c]) next[p][c]=np,p=fa[p];
if(!p) fa[np]=1;
else{
int q=next[p][c];
if(len[q]==len[p]+1) fa[np]=q;
else{
int nq=++cnt;
len[nq]=len[p]+1;
memcpy(next[nq],next[q],sizeof next[nq]);
fa[nq]=fa[q]; fa[np]=fa[q]=nq;
while(next[p][c]==q) next[p][c]=nq,p=fa[p];
}
}
}
void build(char *s){
memset(cntA,0,sizeof(cntA));
memset(A,0,sizeof(A));
for(int i=1;i<=cnt;i++) cntA[len[i]]++;
for(int i=1;i<=cnt;i++) cntA[i]+=cntA[i-1];
for(int i=cnt;i;i--) A[cntA[len[i]]--] =i;
int tmp=1;
int sz=strlen(s);
for(int i=0;i<sz;i++){
num[tmp=next[tmp][s[i]-'a']]=1;
}
for(int i=cnt;i;i--){
int x=A[i];
num[fa[x]]+=num[x];
}
for(int i=1;i<=cnt;i++){
int x=A[i];
sum[x]=sum[fa[x]]+num[x]*(len[x]-len[fa[x]]);
}
}
int query(char *s){
int sz=strlen(s),now=1,Len=0;
int res=0;
for(int i=0;i<sz;i++){
int c=s[i]-'a';
if(next[now][c]){
Len++;
now=next[now][c];
}
else{
while(now&&!next[now][c]) now=fa[now];
if(now){
Len=len[now]+1;
now=next[now][c];
}
else{
Len=0,now=1;
}
}
res+=sum[fa[now]]+num[now]*(Len-len[fa[now]]);
}
return res;
}
}sam;
ll ans[maxn];
char tmp1[maxn];
char tmp2[maxn];
int main()
{
//freopen("in.txt","r",stdin);
scanf("%s",str);
int t;
scanf("%d",&t);
int len=strlen(str);
for(int i=0;i<len-1;i++){
memset(tmp1,0,sizeof(tmp1));
memset(tmp2,0,sizeof(tmp2));
for(int j=0;j<=i;j++) tmp1[j]=str[j];
for(int j=i+1;j<len;j++) tmp2[j-i-1]=str[j];
sam.clear();
int sz=strlen(tmp1);
for(int i=0;i<sz;i++){
sam.Insert(tmp1[i]-'a');
}
sam.build(tmp1);
ans[i+1]=sam.query(tmp2);
}
while(t--){
int n;
scanf("%d",&n);
printf("%lld
",ans[n]);
}
return 0;
}
Problem L
温暖的签到题+1
总结:
状态和节奏都异常稀烂的一场比赛。
全场梦游。开场看到隔壁黄色气球打得异常的多,因此上机直接打找到水题两分钟1y(这里有个小插曲,打完代码之后发现还没登陆,又花了一些时间登陆,再又花了一些时间找如何提交,痛失1血,可能这也是全场比赛的缩影)。
过了L题之后,我全场看题,发现了E是个裸的dancing links,准备掏出板子一端狂抄。此时发现I题已经有不少人A了,看题之后发现这是个多校曾经出过的套路题,我把这题喂给qym之后也成功在20mins 1y。此时看榜,发现E题已经有人过了,C题也已经有人正在尝试,于是我让队友思考C题,我自己独自抄E题的板子。而谁知道,至此就走上了自闭的道路一去而不复返。
大概20min后,我把E题的板子抄完了,但是奈何对原题不是很熟悉,不知道如何读入,试了好多次都无法成功得出正确答案。此时看到C题过题数飙升,队友们也得出了先做一个串,再做另外一个串最后两串合并的算法。因此队友下机,我……因为比赛没有打印系统,我只能对着模板干瞪眼……
过了一段时间之后,qym成功完成了他的算法,交上去1wa。此时已经过去了差不多一个半小时了,看到榜上一堆人3题4题,突然有些慌,再加上连续把IE卡在手上,突然自闭之感油然而生,仿佛梦回去年上半学期……
于是我和lqs对着那100多行的dancing link逐行比较,最后发现N处地方抄错,1个范围写错(orz),最后改了改也成功1y了。
过了E之后,我看了下C题,看完之后口胡出了一个贪心的方法,大家都没意见之后我直接上机,写了一会之后发现 2wa。静下心来debug之后,发现,要初始化没初始化,要塞0的没有塞0。(深度背锅……),把这些弱智错误改完之后才成功3y。
此时已经过去了3个小时了……(然后其实比赛已经结束了)看到榜上AFH都有人开,随跟榜开题。
lqs看到H题之后,发现这题是他和我都做过的某年某个多校的原题的简化版,随开始解释算法思路。但是此时qym说出了另一个很正确的算法。而在我印象中,好像也曾经用这个思路解决了另一个类似的问题,随支开lqs,让qym上机。
但是写完之后很快 1wa,为了避免崩盘(其实已经崩盘了),我去开了A题,发现涉及0/1数位以及数位乘积,想都没想就喂给qym说是数位dp……qym想了一会未果,就又去肝H题了。结果H换了一种又一种的写法还是不断的2wa,3wa……至此陷入无限的自闭之中。
最后半小时,放弃治疗,把H丢了,三个人再开A和F。静下心来看了下A,貌似0/1的数位对答案没有影响……因此这题貌似不是个数位dp,而是对这2-9这8种数分别填到8位的数上……思考过爆搜,但是感觉时间会爆炸,遂没敢上机。而正当F题的思路大概也有了雏形的时候,比赛结束……比赛确实从3小时的时候就结束了。
赛后问了下其他人,H就是个超级大原题,F题的思路就差最后一步,A题直接爆搜即可。
感觉到了下学期之后,三个人的状态和做题感觉越来越差了……换作我们寒假camp的时候,甚至是去年打ec的那段时候,这套题至少能做出6-7个题目,但是过了四五个月之后状态却变得如此稀烂。做一道题卡一道题。这只能证明这四个月时间里面我们的态度太过与懈怠,以至于我们一直在原地踏步(甚至倒退),而大家都在稳步提高。我觉得之后能做的,只能是加大训练量,端正态度,抛弃一些有的没的杂七杂八的侥幸心态了。