zoukankan      html  css  js  c++  java
  • 浙大集训Day10:A.Sequence(双指针)

    浙大集训Day-10:A.Sequence

    我们定义一个序列\(a\),值域\([1,k]\)是好的,当且仅当对于\(1\)\(k\)的每一个数\(j\),在序列里的出现次数都在\([l_j,r_j]\)之间。

    询问有多少个这样的子串,是好的。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+100;
    int n,k,a[maxn];
    int l[maxn],r[maxn];
    int cnt[maxn];
    int cc=0;
    int p1[maxn],p2[maxn];
    int main () {
    	scanf("%d%d",&n,&k);
    	for (int i=1;i<=n;i++) scanf("%d",a+i);
    	for (int i=1;i<=k;i++) scanf("%d%d",l+i,r+i);
    	int L=1,R=1;
    	//先求每个点左边第一个满足的点 
    	cnt[a[1]]=1;
    	for (int i=1;i<=k;i++) if (cnt[i]>=l[i]) cc++;
    	while (1) {
    		while (R<n) {
    			if (cc==k&&R>=L) {
    				//如果已经全部满足,就不用了 
    				break;
    			}
    			else {
    				R++;
    				cnt[a[R]]++;
    				if (cnt[a[R]]==l[a[R]]) cc++;
    			}
    		}
    		if (cc==k) p1[L]=R;
    		cnt[a[L]]--;
    		if (cnt[a[L]]==l[a[L]]-1) cc--;//如果第一次突破下界,cc-- 
    		L++;
    		if (L>n) break;
    	} 
    	
    	L=1,R=1;
    	for (int i=1;i<=k;i++) cnt[i]=0;
    	cnt[a[1]]=1;
    	cc=0;
    	for (int i=1;i<=k;i++) if (cnt[i]>r[i]) cc++;
    	while (1) {
    		while (R<n) {
    			if (cnt[a[R+1]]+1<=r[a[R+1]]) { 
    				R++;
    				cnt[a[R]]++;
    			}
    			else {
    				break;
    			}
    		}
    		if (cc==0) p2[L]=R;
    		cnt[a[L]]--;
    		if (cnt[a[L]]==r[a[L]]) cc--;//如果第一次回到上界,cc-- 
    		L++;
    		if (L>n) break;
    	}
    	long long ans=0;
    	for (int i=1;i<=n;i++) {
    		if (p1[i]>p2[i]) continue;
    		if (!p1[i]||!p2[i]) continue;
    		//printf("%d %d %d\n",i,p1[i],p2[i]);
    		ans+=p2[i]-p1[i]+1;
    	}
    	printf("%lld\n",ans);
    	
    }
    
  • 相关阅读:
    vscode snippet
    OpenGL Type
    [转] fio参数详解
    [转] openchannel SSD( OCSSD)
    [转]linux内存管理
    proc/meminfo && hugepage
    [转] 从free到 page cache
    [转]linux网络协议栈(1)——链路层
    [转]linux 网络协议栈(1)——网络设备
    [转]linux网络协议栈(1)——socket buffer
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15548762.html
Copyright © 2011-2022 走看看