[雅礼集训]program(鬼知道原题叫什么名字。。。)

1 篇文章 0 订阅
1 篇文章 0 订阅

题面:
题目描述

恩。。。部分分比正解难系列。。。目前还是没写出所有询问的r=n的部分。分类讨论太麻烦了。。。

还是说正解:
题解

恩我就是这么懒。。。感觉这一部分讲得肯定比我自己描述清楚;

不过中间有个很重要的细节,由于当一个点为0时,如果立即将其删除,可能他的g[]数组就不会被标记上;
这时候就要延时删除一下;
同时判断一个”<”或”>”是否要删时就需要跳过中间正在被延时删除的点。。。

细节看代码或者自己去实现。。。我这代码直接魔改的暴力,我自己看着都头疼。。。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
const int maxn=100005;
const int inf=1000000007;
int n,t;
char s[maxn],a[maxn];
struct ANSWER{
    int v[10];
    void clear(){
        for(int i=0;i<10;i++)v[i]=0;
    }
    ANSWER operator -(const ANSWER &b){
        ANSWER c;
        c.clear();
        for(int i=0;i<10;i++)c.v[i]=v[i]-b.v[i];
        return c;
    }
}ans[maxn*10];
void write(ANSWER a){
    for(int i=0;i<10;i++)printf("%d ",a.v[i]);
    printf("\n");
}
int next[maxn],front[maxn];
int f[maxn],g[maxn];
void findanslow()
{
        for(int i=1;i<=n;i++)f[i]=g[i]=inf;
        for(int k=1;k<=n;k++)a[k]=s[k];
        for(int k=1;k<=n;k++)next[k]=k+1,front[k]=k-1;
        a[0]='>';
        a[n+1]='>';
        front[1]=0;
        next[0]=1;
        next[n]=0;
        bool flag=true;
        ans[0].clear();
        int tl=0;
        for(int i=1;!(i==0&&flag);i= flag ? next[i]:front[i]){
            tl++;
            ans[tl]=ans[tl-1];
            if(flag==true)f[i]=std::min(tl-1,f[i]);
            if(isdigit(a[i])){
                ans[tl].v[a[i]-'0']++;
                a[i]--;
            }
            else if(a[i]=='>'){
                flag=true;
                if(!i)continue;
                int pos;
                for( pos=next[i];a[pos]<'0';pos=next[pos]);
                if(a[pos]=='>'||a[pos]=='<')a[i]='0'-1;
            }
            else if(a[i]=='<'){
                flag=false;
                int pos;
                for( pos=front[i];a[pos]<'0';pos=front[pos]);
                if(a[pos]=='>'||a[pos]=='<')a[i]='0'-1;
            }else a[i]--;
            if(flag==false)
            {

                for(int k=front[i]+1;k<=i;k++)
                g[i]=std::min(g[i],tl);
            }
            if(a[i]<'0'-1)next[front[i]]=next[i],front[next[i]]=front[i];
        }
        f[n+1]=tl;
}
int main()
{
    freopen("program.in","r",stdin);
    freopen("program.out","w",stdout);
    scanf("%d%d",&n,&t);
    scanf("%s",s+1);
    findanslow();
    ANSWER zero;
    zero.clear();
    for(int i=1;i<=t;i++){
        int tl,tr;
        scanf("%d%d",&tl,&tr);
        int l=f[tl];
        int r=std::min(g[tl],f[tr+1]);
        if(l==inf||r==inf)write(zero);
        else write(ans[r]-ans[l]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值