codeforces 138E. Hellish Constraints

来源:互联网 发布:linux vi 全选复制 编辑:程序博客网 时间:2024/06/04 18:31

给一个字符串s和若干限制,每个限制形如:某字符x出现的次数在l~r之间,问s的子串中恰好满足L~R个限制的有多少个

我们先考虑一个限制
右端点扫过去,维护每个左端点是否满足限制
当新加入一个字符时,
如果它不是当前限制的字符,对每个左端点是否满足没有影响
如果它是,那么他会使x出现次数为l-1的变成满足,出现次数为r的变成不满足
维护一下当前字符第i次出现的位置pos[i],假设当前是第j次出现,那么pos[j-l]+1~pos[j-l+1]会变成满足,pos[j-r-1]+1~pos[j-r]变成不满足,注意到每个位置最多只会被修改2次,所以对于一个限制,这样扫过去是O(n)的
那么将k个限制一起做就好了,复杂度O(nk)

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9using namespace std;const int maxn = 110000;const int maxk = 1100;const int maxv = 26;char str[maxn],s[110];int n,m,L,R;int las[maxv][maxn],col[maxv];int f[maxn];struct node{    int l,r;    node(){}    node(const int _l,const int _r){l=_l;r=_r;}}a[maxv][maxk]; int cnt[maxv];ll ans;int main(){    scanf("%s",str); n=strlen(str);    scanf("%d%d%d",&m,&L,&R);    int ev=0;    for(int i=1;i<=m;i++)    {        int l,r; scanf("%s%d%d",s,&l,&r);        const int w=s[0]-'a';        a[w][++cnt[w]]=node(l,r);        if(l==0) ev++;    }    for(int i=0;i<26;i++) las[i][col[i]=0]=-1;    int now=0;    for(int i=0;i<n;i++)    {        f[i]=ev; if(f[i]>=L&&f[i]<=R) now++;        const int w=str[i]-'a';        las[w][++col[w]]=i;        for(int j=1;j<=cnt[w];j++)        {            if(col[w]>=a[w][j].l)            {                for(int k=las[w][max(0,col[w]-a[w][j].l)]+1;k<=las[w][col[w]-a[w][j].l+1];k++)                {                    f[k]++;                    if(f[k]==L) now++;                    if(f[k]==R+1) now--;                }            }            if(col[w]>a[w][j].r)            {                for(int k=las[w][col[w]-a[w][j].r-1]+1;k<=las[w][col[w]-a[w][j].r];k++)                {                    f[k]--;                    if(f[k]==R) now++;                    if(f[k]==L-1) now--;                }            }        }        ans+=(ll)now;    }    printf("%I64d\n",ans);    return 0;}