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);
}
本文来自博客园,作者:{StranGePants},转载请注明原文链接:https://www.cnblogs.com/StranGePants/p/17830288.html