CF351D - Jeff and Removing Periods 题解
首先做一点显然的转化:在进行第一次操作之后,可以将相同的数排在一起,这样一次就能删掉一种数。如果一开始就能删光一种数的话,那么次数就是区间颜色数,否则就是区间颜色数
所以现在原问题变成了两个问题:求区间内不同颜色数,判断区间内是否有某种颜色满足其出现位置构成等差数列。
第一问是经典问题,可以离线后 BIT 做到
考虑第二问,设
那么原问题相当于是检验
时间复杂度
卡常:不难发现
这样就可以拿到最优解了。
Code:
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define gt getchar
#define pt putchar
#define fst first
#define scd second
#define SZ(s) ((int)s.size())
#define all(s) s.begin(),s.end()
#define pb push_back
#define eb emplace_back
#define re register
typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned long long ull;
typedef unsigned int uint;
const int N=1e5+5;
const int inf=1e9;
const int SIZE=(1<<14);
using namespace std;
using namespace __gnu_pbds;
typedef pair<int,int> pii;
template<class T,class I> inline void chkmax(T &a,I b){a=max(a,(T)b);}
template<class T,class I> inline void chkmin(T &a,I b){a=min(a,(T)b);}
inline bool __(char ch){return ch>=48&&ch<=57;}
inline char gc(){
static char buf[SIZE],*begin=buf,*end=buf;
return begin==end&&(end=(begin=buf)+fread(buf,1,SIZE,stdin),begin==end)?EOF:*begin++;
}
template<class T> inline void read(T &x){
x=0;bool sgn=0;static char ch=gc();
while(!__(ch)&&ch!=EOF) sgn|=(ch=='-'),ch=gc();
while(__(ch)) x=(x<<1)+(x<<3)+(ch&15),ch=gc();
if(sgn) x=-x;
}
template<class T,class ...I> inline void read(T &x,I &...x1){
read(x);
read(x1...);
}
template<class T> inline void print(T x){
static char stk[70];short top=0;
if(x<0) pt('-');
do{stk[++top]=x>=0?(x%10+48):(-(x%10)+48),x/=10;}while(x);
while(top) pt(stk[top--]);
}
template<class T> inline void printsp(T x){
print(x);
putchar(' ');
}
template<class T> inline void println(T x){
print(x);
putchar('\n');
}
int n,m,a[N],pre[N],pos[N],ans[N],mp[N];
vector<pair<pii,int> > vec[N];
vector<pii> qry[N];
int c[N];
inline int lowbit(int x){
return x&(-x);
}
inline void add(int x,int w){
while(x<=n){
c[x]+=w;
x+=lowbit(x);
}
}
inline int query(int x){
int ans=0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
struct Node{
int l,r;
int mn;
}node[N<<2];
inline int lson(int x){
return x<<1;
}
inline int rson(int x){
return x<<1|1;
}
inline void push_up(int p){
node[p].mn=min(node[lson(p)].mn,node[rson(p)].mn);
}
void build(int p,int l,int r){
node[p].l=l,node[p].r=r;
node[p].mn=inf;
if(l==r) return;
int mid=l+((r-l)>>1);
build(lson(p),l,mid);
build(rson(p),mid+1,r);
}
void update(int p,int x,int w){
int l=node[p].l,r=node[p].r;
if(l==r) return node[p].mn=w,void();
int mid=l+((r-l)>>1);
if(x<=mid) update(lson(p),x,w);
else update(rson(p),x,w);
push_up(p);
}
int query(int p,int ql,int qr){
int l=node[p].l,r=node[p].r;
if(ql<=l&&r<=qr) return node[p].mn;
int mid=l+((r-l)>>1),ans=inf;
if(ql<=mid) chkmin(ans,query(lson(p),ql,qr));
if(qr>mid) chkmin(ans,query(rson(p),ql,qr));
return ans;
}
signed main(){
read(n);
for(re int i=1;i<=n;++i){
read(a[i]);
pre[i]=mp[a[i]];
mp[a[i]]=i;
}
for(re int i=1;i<=n;++i){
if(!pre[i]) pos[i]=1;
else if(i-pre[i]==pre[i]-pre[pre[i]]) pos[i]=pos[pre[i]];
else pos[i]=pre[pre[i]]+1;
}
read(m);
for(re int l,r,i=1;i<=m;++i){
read(l,r);
vec[l-1].eb(make_pair(pii(l,i),-1));
vec[r].eb(make_pair(pii(l,i),1));
qry[r].eb(l,i);
}
for(re int r=1;r<=n;++r){
add(pre[r]+1,1);
for(auto qwq:vec[r]){
int l=qwq.fst.fst,id=qwq.fst.scd,w=qwq.scd;
ans[id]+=query(l)*w;
}
}
build(1,1,n);
for(re int r=1;r<=n;++r){
update(1,r,pos[r]);
if(pre[r]) update(1,pre[r],inf);
for(auto qwq:qry[r]){
int l=qwq.fst,id=qwq.scd;
ans[id]+=(query(1,l,r)>l);
}
}
for(re int i=1;i<=m;++i) println(ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】