洛谷P4690 [Ynoi2016] 镜中的昆虫
题目描述
给定一个长度为 \(n\) 的序列 \(a\),有 \(m\) 次操作。共有两种操作:
1 l r x,将 \([l,r]\) 区间赋值为 \(x\)。2 l r,求 \([l,r]\) 中出现了多少种不同的数。
数据范围:\(1\le n,m\le 10^5\),\(a_i\le 10^9\)。
时间范围:\(1500\operatorname{ms}\)。
Solution
直接暴力是 \(O(n^2)\) 的,显然可以通过本题,不需要考虑优化。
对于每个数,求出上一个与这个数相同的位置,定为 \(pre\),没有则为 \(0\)。
对于区间赋值,我们发现当我们会令 \(\forall i\in(l,r],pre_i\leftarrow i-1\),对于 \(i=l\) 特判即可。
同时我们可以发现,当修改位于 \([l,r]\) 中的元素时,与它相同的下一个元素的 \(pre\) 也会变;同时颜色与 \(x\) 相同的位置 \(>r\) 的第一个元素的 \(pre\) 也会变。特判即可。
这一步时间复杂度为 \(O(n)\)。大佬们都写了我就不证了。
那么问题转化为求 \(\sum_{i=l}^{r}[pre_i<l]\),三维数点即可,时间复杂度为 \(O(n\log^2 n)\)。
Code
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
const int maxn=200010,maxq=1000010;
typedef pair<int,int> PII;
struct Data{
int x,y,z,k,d,ans;
inline Data(){}
inline Data(int _x,int _y,int _z,int _k,int _d){x=_x;y=_y;z=_z;k=_k;d=_d;ans=0;}
inline bool operator<(const Data &da)const{return x!=da.x?x<da.x:(y!=da.y?y<da.y:z<da.z);}
}q[maxq],w[maxq/2];
struct Operation{
int opt,l,r,x;
}p[maxn];
int pre[maxn],n,m,tot,a[maxn],b[maxn],cnt,ans[maxn];
inline bool cmpy(const Data &d1,const Data &d2){return d1.y!=d2.y?d1.y<d2.y:d1.z<d2.z;}
struct Color{
set<PII>col,v[maxn];
inline void Split(int k){
set<PII>::iterator it=col.lower_bound(make_pair(k+1,0));
int r=it->first-1;--it;
int l=it->first;
if(k==r)return;
int c=it->second;
col.erase(it);
col.insert(make_pair(l,c));col.insert(make_pair(k+1,c));
v[c].erase(make_pair(l,r));
v[c].insert(make_pair(l,k));v[c].insert(make_pair(k+1,r));
}
inline void Insert(int l,int r,int c,int t){
Split(l-1);Split(r);
for(set<PII>::iterator it=col.lower_bound(make_pair(l,0));it->first<=r;){
int x=it->first,y=it->second;
++it;int z=it->first-1;
col.erase(make_pair(x,y));
v[y].erase(make_pair(x,z));
if(x==l){
int e=(--(v[c].upper_bound(make_pair(x,0))))->second;
if(pre[x]!=e){
q[++tot]=Data(t,x,pre[x],0,-1);
pre[x]=e;
q[++tot]=Data(t,x,pre[x],0,1);
}
}
else{
if(pre[x]!=x-1){
q[++tot]=Data(t,x,pre[x],0,-1);
pre[x]=x-1;
q[++tot]=Data(t,x,pre[x],0,1);
}
}
x=z+1;
z=(v[y].lower_bound(make_pair(x,0)))->first;
int e=(--v[y].lower_bound(make_pair(l,0)))->second;
if(z>r&&z<=n&&pre[z]!=e){
q[++tot]=Data(t,z,pre[z],0,-1);
pre[z]=e;
q[++tot]=Data(t,z,pre[z],0,1);
}
}
set<PII>::iterator it=v[c].lower_bound(make_pair(r+1,0));
int x=it->first;
if(x<=n&&pre[x]!=r){
q[++tot]=Data(t,x,pre[x],0,-1);
pre[x]=r;
q[++tot]=Data(t,x,pre[x],0,1);
}
v[c].insert(make_pair(l,r));
col.insert(make_pair(l,c));
x=r+1;
if(x<=n){
it=col.lower_bound(make_pair(x,0));
int y=it->second;
int e=(--v[y].lower_bound(make_pair(x,0)))->second;
if(pre[x]!=e){
q[++tot]=Data(t,x,pre[x],0,-1);
pre[x]=e;
q[++tot]=Data(t,x,pre[x],0,1);
}
}
}
}color;
struct TreeArray{
#define lowbit(x) (x&-x)
int tr[maxn];
inline void add(int x,int d){++x;while(x<maxn)tr[x]+=d,x+=lowbit(x);}
inline int ask(int x){++x;int ans=0;while(x)ans+=tr[x],x-=lowbit(x);return ans;}
#undef lowbit
}BIT;
inline void CDQ(int l,int r){
if(l>=r)return;
int mid=(l+r)>>1;
CDQ(l,mid);CDQ(mid+1,r);
int i=l,j=mid+1,k=0;
bool flag=(l!=1||r!=tot);
while(i<=mid&&j<=r){
if(q[i].y<=q[j].y){if(q[i].k==0)BIT.add(q[i].z,q[i].d);if(flag)w[k++]=q[i];++i;}
else{if(q[j].k==1)q[j].ans+=BIT.ask(q[j].z);if(flag)w[k++]=q[j];++j;}
}
while(i<=mid){if(q[i].k==0)BIT.add(q[i].z,q[i].d);if(flag)w[k++]=q[i];++i;}
while(j<=r){if(q[j].k==1)q[j].ans+=BIT.ask(q[j].z);if(flag)w[k++]=q[j];++j;}
for(i=l;i<=mid;++i)if(q[i].k==0)BIT.add(q[i].z,-q[i].d);
if(flag)for(int i=0;i<k;++i)q[i+l]=w[i];
}
FILE *read=stdin,*write=stdout;
int main(){
fscanf(read,"%d%d",&n,&m);
for(int i=1;i<=n;++i)fscanf(read,"%d",&a[i]),b[++cnt]=a[i];
for(int i=1;i<=m;++i){
fscanf(read,"%d%d%d",&p[i].opt,&p[i].l,&p[i].r);
if(p[i].opt==1)fscanf(read,"%d",&p[i].x),b[++cnt]=p[i].x;
}
sort(b+1,b+cnt+1);
cnt=unique(b+1,b+cnt+1)-b-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
for(int i=1;i<=m;++i)if(p[i].opt==1)p[i].x=lower_bound(b+1,b+cnt+1,p[i].x)-b;
for(int i=1;i<=cnt;++i)
color.v[i].insert(make_pair(0,0));
for(int i=1;i<=n;++i){
pre[i]=(--color.v[a[i]].end())->second;
q[++tot]=Data(0,i,pre[i],0,1);
color.v[a[i]].insert(make_pair(i,i));
color.col.insert(make_pair(i,a[i]));
}
for(int i=1;i<=cnt;++i)
color.v[i].insert(make_pair(n+1,0));
color.col.insert(make_pair(0,0));
color.col.insert(make_pair(n+1,n+1));
for(int i=1;i<=m;++i){
if(p[i].opt==1)
color.Insert(p[i].l,p[i].r,p[i].x,i);
else{
q[++tot]=Data(i,p[i].r,p[i].l-1,1,1);
q[++tot]=Data(i,p[i].l-1,p[i].l-1,1,-1);
}
}
sort(q+1,q+tot+1);
CDQ(1,tot);
for(int i=1;i<=tot;++i)
if(q[i].k)ans[q[i].x]+=q[i].ans*q[i].d;
for(int i=1;i<=m;++i)
if(p[i].opt==2)fprintf(write,"%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号