hdu 5672 String

线段树+模拟


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
char str[1000005];
int T[26<<2];
int M;
inline void build()
{
    for(M=1;M<28;M<<=1);
    memset(T,0,sizeof(int)*(M+M));
}
void pushup(int x)
{
    T[x>>=1]=0;    
    if(T[x<<1])T[x]++;
    if(T[x<<1|1])T[x]++;
    for(x>>=1;x;x>>=1)
        T[x] = T[x<<1] + T[x<<1|1];
}
void add(int x)
{
    T[x+=M]++;
    if(T[x]==1)
        pushup(x);
}
void sub(int x)
{
    T[x+=M]--;
    if(T[x]==0)
        pushup(x);
}
#define query() T[1]
int main()
{
    int n,k;
    scanf("%d",&n);
    while(n--)
    {
        long long ans = 0;
        scanf("%s%d",str+1,&k);
        int len = strlen(str+1);
        int pa = 1;
        int pb = 1;
        //[pa,pb]
        build();
        for(;pb<=len;pb++)
        {
            add(str[pb]-'a'+1);
            if(query() == k)
            {
                while(query()==k)
                    sub(str[pa++]-'a'+1);
                add(str[--pa]-'a'+1);
                ans += pa;
            }
            if(query()>k)
            {
                do{
                    sub(str[pa++]-'a'+1);
                }while(query()>k);
                while(query()==k)
                    sub(str[pa++]-'a'+1);
                add(str[--pa]-'a'+1);
                ans +=pa;
            }
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值