码蹄杯2026省赛第三轮/ccpc吉林省赛部分赛后补题

码蹄杯 2026.5.24



刺累自尽毕 MC0574

给定 \(a_1\) ~ \(a_n\) ,有 \(m\) 次询问,每次询问一个整数 \(L\) ,问所有长度为 \(L\) 的连续子段的数字种类数之和是多少。
例如序列 \(a=[2,2,3,1]\) ,所有长度为2的连续子段为 \([2,2]\)\([2,3]\)\([3,1]\) ,数字种类数分别为1,2,2。问询的答案为1+2+2=5。
其中 \(1\le n,m\le10^6\)\(1\le a_i,L \le n\)

考虑每一个位置上的数字 \(a_i\) 对答案的贡献。在同一个子段内,出现了两个及以上的相同数字,只认为第一个数字是对答案有效贡献的。

例如 \(a=[2,2,3,1]\) ,问询 \(L=2\)时,子段 \([2,2]\) 只认为第一个2有贡献。这样我们在统计每一个位置 \(i\) 上的数字时,能影响到的区间 \([l,r]\)\(l\) 范围应该设定为 \([pre[i]+1,i]\) ,其中 \(pre[i]\) 表示位置 \(i\) 的前一个相同数字的位置;而 \(r\) 的范围应该设定为 \([i,n]\)

现在考察位置 \(i\) ,假设左端点所在的区间长度为3,右端点的区间长度为7,考虑其对 \(L=1,2,3...\) 分别的影响。


\(L=1\) ,只能取区间 \([i]\)
\(L=2\) ,取区间 \([i-1,i]\)\([i,i+1]\)
\(L=3\) ,取区间 \([i-2,i-1,i]\)\([i-1,i,i+1]\)\([i,i+1,i+2]\)
\(L=4\) ,取区间 \([i-2,i-1,i,i+1]\)\([i-1,i,i+1,i+2]\)\([i,i+1,i+2,i+3]\)
\(......\)


\(a\) 为左右端点区间长度较小值, \(b\) 为左右端点区间长度较大值。
不难看出,当 \(L\le a\) 时,答案贡献数等于 \(L\)
\(a\le L \le b\) 时,答案贡献数为 \(a\)
\(b\le L \le a+b\) 时,答案贡献数为 \(a+b-L\)

答案贡献数的形状是一个梯形。

可以考虑用二阶差分 \(O(n)\) 的维护每一个位置的贡献。

例子里的 \(a_i\)对答案数组 \(ans[1,9]\) 的影响 \(1,2,3,3,3,3,3,2,1\) 一次差分可以拆解为形如 \(1,1,1,0,0,0,0,-1,-1,-1\) 的形式,再一次拆解可以变成 \(1,0,0,-1,0,0,0,-1,0,0,1\) 的形式。

实现如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 

const int MAXN = 1e6+25;
inline ll read(){
	ll w=1,q=0;char ch=' ';
	while(w!='-' && (ch<'0' || ch>'9')) ch=getchar();
	if(ch=='0') w=-1,ch=getchar();
	while(ch<='9' && ch>='0') q=q*10+ch-'0',ch=getchar();
	return w*q;
}

ll n,m,a[MAXN];
ll mem[MAXN],pre[MAXN],d1[MAXN],d2[MAXN],ans[MAXN];

signed main(){
	n=read(),m=read();
	for(int i=1; i<=n; i++) a[i]=read();
	for(int i=1; i<=n; i++){
		pre[i] = mem[a[i]];
		mem[a[i]] = i;
	}
	for(int i=1; i<=n; i++){
		int a = i-pre[i];
		int b = n-i+1;
		int p = min(a,b),q = max(a,b);
		d1[1] += 1;
		d1[p+1] -= 1;
		d1[q+1] -= 1;
		d1[p+q+1] += 1;
	}
	for(int i=1; i<=n; i++){
		d2[i] = d2[i-1]+d1[i]; 
	}
	for(int i=1; i<=n; i++){
		d2[i] += d2[i-1];
	}
	for(int i=1; i<=m; i++){
		cout<<d2[read()]<<endl;
	} 
	return 0;
} 
posted @ 2026-05-26 15:42  smy2006  阅读(43)  评论(0)    收藏  举报