814C An impassioned circulation of affection

这里写图片描述

思路: 链表模拟。 比如样例 koyomi 对26个字母 都创建一条链表,比如字母’o’ 2->3->-1(前向星逆)

对于每个询问 mi(活力值) ci(字母) 有滑动窗口模拟(队列) 对于链表下一跳,当前活力值够就跳。进队,更新。。不够,就队头往后缩。 恢复活力值,继续判断能否往后跳…….直到链表的尽头。

#include <cstdio>
#include <bitset>
#include <iostream>
#include <set>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include<stdio.h>
#include<string.h>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long

const int maxn=1000000;
int n;
char s[3000];
bool cmp(const int &e1,const int &e2){
    return e1>e2;
}
int head[3000];
int tot;
void init(){
    for(int i=0;i<30;i++)head[i]=-1;
    tot=0;
}
struct Edge{
    int to,next,w;
}e[maxn];
void addedge(int from,int to,int w){
    e[tot].to=to;e[tot].next=head[from];e[tot].w=w;head[from]=tot++;
}
int que[100000];
int main() {
    if(fopen("H:\\acm.txt", "r")!=NULL){
     freopen("H:\\acm.txt","r",stdin);
     }

    while(scanf("%d",&n)!=EOF){

        int vis[50];memset(vis,0,sizeof(vis));
        scanf("%s",s+1);
        init();
        for(int i=0;i<26;i++){
            char x=i+'a';
            for(int j=1;j<=n;j++){
                    int sb=j;
                if(s[j]=='a'+i){
                    int w=1;
                    while(j+1<=n&&s[j+1]=='a'+i){
                        w++; j++;
                    }
                    addedge(i,sb,w);
                }
            }
        }
        for(int i=0;i<26;i++){

            int u=head[i]; head[i]=-1;
            for(;u!=-1;u=e[u].next){
                addedge(i,e[u].to,e[u].w);
            }
        }
        int qn,q;char g[10];
        cin>>qn;
        for(int ii=1;ii<=qn;ii++){

            cin>>q>>g;
            int stq=q;
            int st=0,ed=0;
            int now,res=0;
             int u=g[0]-'a';
            if(head[u]==-1){
                printf("%d\n",min(q,n) );continue;
            }
            int final_res=0;

            int ei=head[u];
            res+=e[ei].w;
            int k=e[ei].next;
            que[ed++]=ei;
            final_res=max(final_res,res);
            final_res=max(final_res,min(res+q,n));
            for( ;k!=-1;k=e[k].next ){

                 int len=e[k].to-(e[que[ed-1]].to+e[que[ed-1]].w );
                 if(len<=q){
                    q-=len;
                      res+=len+e[k].w;
                         que[ed++]=k;
                        final_res=max(final_res,res);
                        final_res=max(final_res,min(res+q,n));
                        continue;

                 }

                 while(ed-st>=2){
                      int tlen=e[que[st+1]].to-(e[que[st]].to+e[que[st]].w) ;
                      q+=tlen;

                      res-=tlen+e[que[st]].w;
                        st++;
                      if(len<=q){
                        break;
                      }
                 }

                 if(len<=q){
                        q-=len;
                        res+=len+e[k].w;
                        que[ed++]=k;
                        final_res=max(final_res,res);
                        final_res=max(final_res,min(res+q,n) );
                        continue;
                 }else{
                        final_res=max(final_res,min(res+q,n) );
                        res=0;st=0,ed=0;q=stq;
                            res+=e[k].w;
                            que[ed++]=k;
                            final_res=max(final_res,res);
                            final_res=max(final_res,min(res+q,n) );
                 }
            }

                if(q>0){
                    final_res=max(final_res,min(res+q,n) );
                }
                printf("%d\n",final_res);
        }
    }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值