Goose, Goose, DUCK?

Goose, Goose, DUCK?
对于这种确定 L,R 可简单求出区间答案的问题,我们常常考虑通过固定端点,移动另一端计算贡献。
具体的,我们移动 R,计算[1,R]中的点对答案的贡献。
假设某个值在 [1,R] 中出现位置为 \(1\leq a_1,a_2...a_m\leq R\),可以得出不合法区间为 [\(a_{m-k}+1,a_{m-k+1}\)]。
随着 R 向右移,不合法区间随之更新。并且[1,R]内某个点只要对于一个值是不合法的,那么这个点就不合法。
对于新增的不合法区间进行区间+1,撤销时进行区间-1,不难看出区间内0的个数即为合法点。
那么线段树维护区间最小值即最小值个数即可。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<bitset>
using namespace std;
#define db double
#define ll long long
#define ull unsigned long long
#define ld long double
#define b1t bitset
#define ls p<<1
#define rs p<<1|1
const int MAXN=1e6+5;
const int INF=0x3f3f3f3f;
const int UP=1e9;
const int Mod=1e9+7;
void read(int &x){
	x=0;int f=1;char s=getchar();
	while(s<'0'||s>'9'){
		if(s=='-') f=-1;s=getchar();
	}
	while(s>='0'&&s<='9'){
		x=(x<<3)+(x<<1)+(s^48);s=getchar();
	}
	x*=f;
}
ll ksm(ll a,int b){
	ll res=1;
	while(b){
		if(b&1) res=res*a%Mod;a=a*a%Mod;b>>=1;
	}return res;
}
int n,tag[MAXN<<2],ma,va[MAXN],KK;
vector<int> v[MAXN];
ll Ans;
struct tree{
	int va,con;
	tree operator+(const tree &a)const{
		tree c;c.con=0;c.va=min(va,a.va);
		if(c.va==a.va) c.con+=a.con;
		if(c.va==va) c.con+=con;
		return c;
	}
	void clear(){
		va=INF;con=0;
	}
}t[MAXN<<2];
void pup(int p){
	t[p]=t[ls]+t[rs];
}
void pdo(int p){
	if(tag[p]!=0){
		t[ls].va+=tag[p];t[rs].va+=tag[p];
		tag[ls]+=tag[p];tag[rs]+=tag[p];
		tag[p]=0;
	}
}
void bui(int p,int l,int r){
	t[p].va=0;tag[p]=0;
	if(l==r){
		t[p].con=1;return;
	}
	int mid=(l+r)>>1;
	bui(ls,l,mid);bui(rs,mid+1,r);
	pup(p);
}
void modi(int p,int l,int r,int ql,int qr,int x){
	if(l>=ql&&r<=qr){
		t[p].va+=x;tag[p]+=x;return;
	}
	pdo(p);
	int mid=(l+r)>>1;
	if(ql<=mid) modi(ls,l,mid,ql,qr,x);
	if(qr>mid) modi(rs,mid+1,r,ql,qr,x);
	pup(p);
}
tree que(int p,int l,int r,int ql,int qr){
	if(l>=ql&&r<=qr) return t[p];
	pdo(p);
	int mid=(l+r)>>1;tree tmp;tmp.clear();
	if(ql<=mid) tmp=tmp+que(ls,l,mid,ql,qr);
	if(qr>mid) tmp=tmp+que(rs,mid+1,r,ql,qr);
	return tmp;
}
int main(){
	read(n);read(KK);
	for(int i=1;i<=n;i++){
		read(va[i]);ma=max(ma,va[i]);
	}
	bui(1,1,n);
	for(int i=1,L,R;i<=n;i++){
		if((int)v[va[i]].size()>=KK){
			if((int)v[va[i]].size()==KK) L=1,R=v[va[i]][0];
			else L=v[va[i]][v[va[i]].size()-KK-1]+1,R=v[va[i]][v[va[i]].size()-KK];
			modi(1,1,n,L,R,-1);
		}
		v[va[i]].emplace_back(i);
		if((int)v[va[i]].size()>=KK){
			if((int)v[va[i]].size()==KK) L=1,R=v[va[i]][0];
			else L=v[va[i]][v[va[i]].size()-KK-1]+1,R=v[va[i]][v[va[i]].size()-KK];
			modi(1,1,n,L,R,1);
		}
		tree tmp=que(1,1,n,1,i);
		if(tmp.va==0) Ans+=tmp.con;
	}
	printf("%lld",Ans);
}
posted @ 2023-11-13 21:46  StranGePants  阅读(15)  评论(0编辑  收藏  举报