题目大意:
题目链接:https://jzoj.net/senior/#main/show/4804
思路:
显然的,对于任意一个确定的,满足题目要求的序列左端点肯定是一段连续的区间。
而且这个区间显然是满足单调性的。
所以可以用三个指针维护。每次把指针右移一位时维护和,然后答案累加就可以了。
均摊时间复杂度为
代码:
**#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=200010;
int n,m,l1,l2,r,sum,a[N],L[N],R[N],cnt1[N],cnt2[N];
ll ans;
int main()
{
freopen("survey.in","r",stdin);
freopen("survey.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&L[i],&R[i]);
if (!L[i]) sum++;
}
l1=l2=1;
for (r=1;r<=n;r++)
{
cnt1[a[r]]++;
cnt2[a[r]]++;
if (cnt2[a[r]]==L[a[r]]) sum++;
while (cnt1[a[r]]>R[a[r]])
{
cnt1[a[l1]]--;
l1++;
}
while (sum==m&&l2<=r)
{
cnt2[a[l2]]--;
if (cnt2[a[l2]]==L[a[l2]]-1) sum--;
l2++;
}
ans+=max((ll)l2-(ll)l1,0LL);
}
printf("%lld
",ans);
return 0;
}