这题难读得很,英语硬伤了。。可以理解为一排高度为等差数列的柱子,给一些询问,对每个询问,每次能砍掉m根柱子1个单位的高度,砍t次,需要回答能从l开始连续砍光几根。
思路是二分。因为肯定砍不到高度大于t的柱子,所以先找出高度不大于t的右边界,拿来和l二分。二分时比较的是这些柱子的总高度和能砍的总高度。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll A,B,n;
ll calc(ll l,ll r){
ll re= (A+(l-1)*B + A+(r-1)*B)*(r-l+1)/2;
return re;
}
int main(){
cin>>A>>B>>n;
ll l,t,m;
for(int i=1;i<=n;i++){
scanf("%I64d%I64d%I64d",&l,&t,&m);
ll maxR=(t-A)/B+1;
ll tot = t*m;
if(maxR<l){
printf("-1\n");
}else{
ll curl=l;
ll curr=maxR;
ll mid=curr;
ll ans=curr;
while(curl<=curr){
mid=(curl+curr)/2;
if(calc(l,mid)<=tot){
curl=mid+1;
ans=mid;
}else{
curr=mid-1;
}
}
printf("%I64d\n",ans);
}
}
return 0;
}
B Tavas and Malekas
原串为s,模式串p,全部都由小写英文字母组成,你知道一些肯定匹配的位置,计算s有多少种存在的可能。
其实这题就是KMP,在串s中,把那些匹配的p填进去,然后根据空出来的位置计算就好。填进去的时候,如果完全暴力,肯定会超时,这就需要用KMP来优化,并检测冲突,如果冲突了,答案就是0,否则就是26的空槽数次幂。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
char p[1000010];
int y[1000010];
int _next[1000010];
int n,m;
bool s[1000010];
int lenp;
void find_next(){
int k=0;
lenp=strlen(p+1);
for(int i=2;i<=lenp;i++){
while(p[i]!=p[k+1]){
k=_next[k];
if(k==0)break;
}
if(p[i]==p[k+1])k++;
_next[i]=k;
}
}
int main(){
cin>>n>>m;
scanf("%s",p+1);
find_next();
for(int i=1;i<=m;i++){
scanf("%d",&y[i]);
}
if(m){
for(int i=y[1];i<y[1]+lenp;i++){
s[i]=1;
}
}
for(int i=2;i<=m;i++){
if(y[i]-y[i-1] < lenp ){
int target=lenp-(y[i]-y[i-1]);
bool ok=0;
int cur=lenp;
while(1){
cur=_next[cur];
if(cur==0)break;
if(cur==target){
ok=1;
break;
}
}
if(ok==1){
for(int j=y[i-1]+lenp;j<y[i]+lenp;j++){
s[j]=1;
}
}else{
printf("0\n");
return 0;
}
}else{
for(int j=y[i];j<y[i]+lenp;j++){
s[j]=1;
}
}
}
ll ans=1;
for(int i=1;i<=n;i++){
if(!s[i]){
ans*=26;
ans%=mod;
}
}
cout<<ans<<endl;
return 0;
}
本文解析两道算法竞赛题目,一是通过二分查找解决柱子砍伐问题,二是利用KMP算法处理字符串匹配挑战,详细阐述了解题思路及代码实现。

被折叠的 条评论
为什么被折叠?



