P3792 由乃与大母神原型和偶像崇拜

给你一个长为 \(n\) 的序列 \(a\)
每次两个操作:

  1. 修改 \(x\) 位置的值为 \(y\)
  2. 查询区间 \([l,r]\) 是否可以重排为值域上连续的一段

我写的是一种保证了正确性的做法。
带修莫队+线段树。
用线段树来查询区间最大最小,用莫队来查询区间是否有重复数字。
一个小优化是当线段树的查询已经不满足的时候就不用莫队移动指针了。
2.5e7的int是开的下的,不要像我一样一开始开map直接被卡死。

点击查看代码
#include<bits/stdc++.h>
#define p_b push_back
#define e_b emplace_back
#define ll long long
#define pii pair<int,int>
#define fir first
#define sec second
#define il inline
#define gc getchar
#define ios ios::sync_with_stdio(0),cin.tie(0)
using namespace std;
const int N=5e5+1,inf=1e9;
inline int read(){
    int x=0;
    bool f=0;
    char ch=gc();
    while(ch<'0'||ch>'9')f=ch=='-',ch=gc();
    while('0'<=ch&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=gc();
    return f?-x:x;
}
int n,a[N],len,m,bsz,b[N],t[N];
int mx[N<<2],mi[N<<2];
il void build(int p,int l,int r){
    if(l==r){mx[p]=mi[p]=a[l];return;}
    int mid=l+r>>1;
    build(p<<1,l,mid),build((p<<1)|1,mid+1,r);
    mx[p]=max(mx[p<<1],mx[(p<<1)|1]);
    mi[p]=min(mi[p<<1],mi[(p<<1)|1]);
}
il void upd(int p,int l,int r,int k,int x){
    if(l==r){mx[p]=mi[p]=x;return;}
    int mid=l+r>>1;
    if(k<=mid)upd(p<<1,l,mid,k,x);
    else upd((p<<1)|1,mid+1,r,k,x);
    mx[p]=max(mx[p<<1],mx[(p<<1)|1]);
    mi[p]=min(mi[p<<1],mi[(p<<1)|1]);
}
il int find_mx(int p,int l,int r,int ql,int qr){
    if(qr<l||ql>r)return 0;
    if(ql<=l&&r<=qr)return mx[p];
    int mid=l+r>>1,res=0;
    if(ql<=mid)res=find_mx(p<<1,l,mid,ql,qr);
    if(qr>mid)res=max(res,find_mx((p<<1)|1,mid+1,r,ql,qr));
    return res;
}
il int find_mi(int p,int l,int r,int ql,int qr){
    if(qr<l||ql>r)return 1e9;
    if(ql<=l&&r<=qr)return mi[p];
    int mid=l+r>>1,res=1e9;
    if(ql<=mid)res=find_mi(p<<1,l,mid,ql,qr);
    if(qr>mid)res=min(res,find_mi((p<<1)|1,mid+1,r,ql,qr));
    return res;
}
int ux[N],uf[N],ut[N],u;
struct Qry{
    int l,r,id,ti;
}q[N];
bool cmp(Qry x,Qry y){
    return b[x.l]^b[y.l]?b[x.l]<b[y.l]:b[x.r]^b[y.r]?(b[x.l]&1?b[x.r]>b[y.r]:b[x.r]<b[y.r]):(b[x.r]&1?x.ti>y.ti:x.ti<y.ti);
}
int cnt[25000001],now;
void del(int p){now-=!(--cnt[a[p]]);}
void add(int p){now+=!(cnt[a[p]]),cnt[a[p]]++;}
bool ans[N];
signed main(){
    n=read(),m=read();
    bsz=n/sqrt(m);//T.reset();
    for(int i=1;i<=n;i++){a[i]=read(),b[i]=(i-1)/bsz+1;t[i]=a[i];}
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int op,x,y;
        op=read(),x=read(),y=read();
        if(op-1){
            q[++len].l=x,q[len].r=y,q[len].id=len,q[len].ti=u;
            int mx=find_mx(1,1,n,x,y),mi=find_mi(1,1,n,x,y);
            if(mx-mi^y-x)ans[len]=1;
        }
        else ux[++u]=x,uf[u]=t[x],ut[u]=y,t[x]=y,upd(1,1,n,x,y);
    }
    sort(q+1,q+len+1,cmp);
    int l=1,r=0,ti=u;
    for(int i=1;i<=len;i++){
        if(ans[q[i].id])continue;
        int ql=q[i].l,qr=q[i].r;
        while(ti<q[i].ti){
            int p=ux[++ti],to=ut[ti];
            if(l<=p&&p<=r)del(p);
            a[p]=to;upd(1,1,n,p,to);
            if(l<=p&&p<=r)add(p);
        }
        while(ti>q[i].ti){
            int p=ux[ti],f=uf[ti];
            if(l<=p&&p<=r)del(p);
            a[p]=f;upd(1,1,n,p,f);
            if(l<=p&&p<=r)add(p);
            --ti;
        }
        int mx=find_mx(1,1,n,ql,qr),mi=find_mi(1,1,n,ql,qr);
        while(l<ql)del(l++);
        while(l>ql)add(--l);
        while(r<qr)add(++r);
        while(r>qr)del(r--);
        //int mx=find_mx(1,1,n,l,r),mi=find_mi(1,1,n,l,r);
        ans[q[i].id]=(mx-mi+1^r-l+1)|(now^r-l+1);
    }
    for(int i=1;i<=len;i++)
        if(ans[i])puts("yuanxing");
        else puts("damushen");
}
posted @ 2025-10-10 15:07  zhuoheng  阅读(8)  评论(4)    收藏  举报