题解:CF351D Jeff and Removing Periods
这是一个截然不同的,只需要普通线段树的,高贵的
由题目可知,每次删除后可以重排列这个序列,而每次删除只能删掉颜色相同的一个等差数列。因此我们每次重新排列时只要把相同颜色的全部放到最前面,由于一个前缀一定是一个等差数列,因此我们可以把一种颜色全部删除。
但是问题就在于第一次操作前时不能重排的,所以第一次删除不一定能删完一种颜色。
于是问题就转换成判断是否存在一种颜色可以一次删完,即判断是否有一种颜色在给定区间钟的位置是等差数列。如果存在,答案就是区间的颜色数量;否则就是颜色数量
那么我们对于每个
- 假设
i 为最大的i 满足i \isin [l,r] 且b_i = c ,并且\text{lst}_{\text{pos}_i} < l 。
为什么呢?首先我们取最大的
我们知道,区间数颜色问题有广为人知的
那么这道题就做完了,复杂度为
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define N 1000006
using namespace std;
int n,q,a[N],lst[N],t[N],pos[N],ans[N];
vector<pair<int,int> > Q[N];
struct Segtree1{
int tree[N];
void build(int p,int l,int r)
{
if(l==r)return tree[p]=1,(void)0;
int mid=l+r>>1;build(p<<1,l,mid),build(p<<1|1,mid+1,r);
tree[p]=tree[p<<1]+tree[p<<1|1];
}
void update(int p,int l,int r,int k)
{
if(l==r)return tree[p]=0,(void)0;
int mid=l+r>>1;k<=mid?update(p<<1,l,mid,k):update(p<<1|1,mid+1,r,k);
tree[p]=tree[p<<1]+tree[p<<1|1];
}
int query(int p,int l,int r,int L,int R)
{
if(L<=l&&r<=R)return tree[p];
int mid=l+r>>1,ret=0;
if(L<=mid)ret+=query(p<<1,l,mid,L,R);
if(R>mid)ret+=query(p<<1|1,mid+1,r,L,R);
return ret;
}}T1;
struct Segtree2{
int tree[N];
void build(int p,int l,int r)
{
if(l==r)return tree[p]=1e15,(void)0;
int mid=l+r>>1;build(p<<1,l,mid),build(p<<1|1,mid+1,r);
}
void update(int p,int l,int r,int k,int x)
{
if(l==r)return tree[p]=x,(void)0;
int mid=l+r>>1;k<=mid?update(p<<1,l,mid,k,x):update(p<<1|1,mid+1,r,k,x);
tree[p]=min(tree[p<<1],tree[p<<1|1]);
}
int query(int p,int l,int r,int L,int R)
{
if(L<=l&&r<=R)return tree[p];
int mid=l+r>>1,ret=1e15;
if(L<=mid)ret=min(ret,query(p<<1,l,mid,L,R));
if(R>mid)ret=min(ret,query(p<<1|1,mid+1,r,L,R));
return ret;
}}T2;
main()
{
scanf("%lld",&n),T1.build(1,1,n),T2.build(1,1,n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]),lst[i]=t[a[i]],t[a[i]]=i;
for(int i=1;i<=n;i++)
{
if(!lst[i])pos[i]=i;
else if(i-lst[i]==lst[i]-lst[lst[i]]||!lst[lst[i]])pos[i]=pos[lst[i]];
else pos[i]=lst[i];
}
scanf("%lld",&q);
for(int i=1,l,r;i<=q;i++)
scanf("%lld%lld",&l,&r),Q[r].push_back({l,i});
for(int i=1;i<=n;i++)
{
T2.update(1,1,n,i,lst[pos[i]]);
if(lst[i])T1.update(1,1,n,lst[i]),T2.update(1,1,n,lst[i],1e15);
for(auto [l,id]:Q[i])
ans[id]=T1.query(1,1,n,l,i)+(T2.query(1,1,n,l,i)>=l);
}
for(int i=1;i<=q;i++)printf("%lld\n",ans[i]);
return 0;
}