Problem 3 疯狂的限制(lunatic.cpp/c/pas)
【题目描述】
[题目简述]
给定k个限制条件,其中第i个条件用c[i],l[i],r[i]表示:
字符c[i]在字符串中的出现次数大等于l[i],小等于r[i]。
若一个字符串满足的限制条件的个数大等于L,小等于R,则称该串为StenisString
给定一小写字母串s,求s有多少个子串是SteinsString。
OkabeRintarou觉得一般的字符串问题弱爆了,所以他自己编了道题目:
内嵌[题目简述]
结果这题被桶子秒了。
“正因无意义才有其存在意义。”
【输入格式】
第一行一个非空的小写字母串s
第二行三个整数k,L,R。
以下k行,每行1个字符和2个整数表示c[i],l[i],r[i]
【输出格式】
一个整数,表示答案
【样例输入】
elpsycongroo
3 1 2
o 2 4
a 1 2
y 1 3
【样例输出】
48
【数据范围】
对于10%的数据 k=1,|s|<=200
对于30%的数据 k<=100,|s|<=200
对于另外30%的数据 L=R=K
对于100%的数据 0<=L<=R<=k<=500,0<=l[i]<=r[i]<=|s|,|s|<=10^5
这题解法是
Case 1:枚举区间右端点
Case 2:a[x]表示以x为左端点满足的条件数
Case 3:暴力确定所有条件,可以发现每个条件对区间的影响是1段+1,1段-1
Case 4:到这里就不会了(弱TNT),从上午2点弄到现在……
看来Dp要加强了……(连暴力都不会的X1)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define MAXN (100000+10)
#define MAXK (500+10)
#define MAXDy (26)
struct seg
{
int l,r;
seg():l(0),r(0){}
}line;
int n,m,k,L,R,l[MAXK],r[MAXK],a[MAXN]={0};
char s[MAXN],c[MAXK];
int su[MAXDy][MAXN]={0},p[MAXDy]={0},tot=0;
long long ans=0;
bool check(int i,int j)
{
int t=0;
// if (s[i]==c[j]) t++;//cout<<t<<' '<<s[i]<<' '<<c[j]<<' ';
if (l[j]<=t&&t<=r[j]) return 1;return 0;
}
void add(int l,int r,int c)
{
// cout<<':'<<l<<' '<<r<<' '<<c<<endl;
Fork(i,l,r)
{
if (L<=a[i]&&a[i]<=R) tot--;
a[i]+=c;
if (L<=a[i]&&a[i]<=R) tot++;
}
}
int main()
{
scanf("%s\n",s+1);s[0]=' ';n=strlen(s)-1;
scanf("%d%d%d\n",&m,&L,&R);
For(i,m) scanf("%c%d%d\n",&c[i],&l[i],&r[i]);
For(i,n) su[s[i]-'a'][++su[s[i]-'a'][n+1]]=i;
For(i,n)
{
p[s[i]-(int)'a']++;//cout<<tot<<' ';
/* un L 原来满足要求 */
For(j,m) if (!l[j]) a[i]++;
if (L<=a[i]&&a[i]<=R) tot++;//cout<<tot<<' ';
/*
For(j,m) a[i]+=check(i,j);//,cout<<a[i]<<' ';
if (L<=a[i]&&a[i]<=R) tot++;//cout<<tot<<' ';
*/
For(j,m)
{
if (c[j]^s[i]) continue;
if (p[s[i]-'a']-1>=r[j]) add(su[s[i]-'a'][p[s[i]-(int)'a']-r[j]-1]+1,su[s[i]-'a'][p[s[i]-(int)'a']-r[j]],-1);
if (l[j]&&p[s[i]-'a']-1>=l[j]-1) add(su[s[i]-'a'][p[s[i]-'a']-l[j]]+1,su[s[i]-'a'][p[s[i]-'a']-l[j]+1],1);
}
ans+=(long long)tot;
/*
cout<<tot<<' '<<endl;
For(j,i) cout<<a[j]<<' ';cout<<endl;*/
}
cout<<ans<<endl;
return 0;
}