ABC237题解

2025-01-13 ABC237

F. |LIS|= 3

题意:

数列 A 满足要求当且仅当其长度为 N,各项值都为小于等于 M 的正整数且其 LIS 为 3 。
求满足要求的数列的个数。答案对 998244353 取模。

3N1000,3M10

解法:

一道 dp,状态设计比较高妙。

dpi,a,b,c 表示当前取到第 i 位,长为 1,2,3 的严格单调上升子序列最后位最小值分别为 a,b,c 的方案数。于是 dpi,a,b,c 可以转移到

{dpi+1,x,b,cxadpi+1,a,x,ca<xbdpi+1,a,b,xb<xc

最终答案即为a=1m2b=a+1m1c=b+1mdpn,a,b,c


G. Range Sort Query

题意:

有一个长 N 的排列 P 和一个正整数 X
Q 次操作,共有两种操作:
1 l r 将区间 [l,r] 升序排序。
2 l r 将区间 [l,r] 降序排序。
输出操作完 X 的位置。

1N,Q2×105

解法:

并没有想到,也没做过 P2824,看了题解才会……但是确实是很高妙的方法。

由于题目所求的是 X 最终位置,所以除 X 以外的数最终位置是无所谓的,只需要关注它们与 X 的相对位置。
考虑令 <X 的数为 0X 的数为 1,显然进行排序操作后 <X 的数与 X 的数相对位置是正确的,那么就可以使用线段树维护这样的操作。

具体来说,统计区间和,把左侧或右侧区间修改为 1 ,把另一侧修改为 0

但是我们无法就此得到 X 的位置,所以我们把 0 的条件改为 X ,最后序列中不同的数的位置即为 X 的位置。

Code (C++)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define il inline
#define pb push_back
#define ls (nw<<1)
#define rs ((nw<<1)|1)
#define mid ((l+r)>>1)
const int N=2e5+10;
int n,a[N],num;
struct Segment_Tree{
    int t[N<<2],lz[N<<2];
    il void pu(int nw){t[nw]=t[ls]+t[rs];}
    il void pd(int l,int r,int nw){
        if(lz[nw]==1){
            t[ls]=mid-l+1,t[rs]=r-mid;
            lz[ls]=lz[rs]=1;
            lz[nw]=0;
        }
        else if(lz[nw]==-1){
            t[ls]=t[rs]=0;
            lz[ls]=lz[rs]=-1;
            lz[nw]=0;
        }
    }
    void bild1(int l,int r,int nw){
        if(l==r){
            if(a[l]<num)t[nw]=0;
            else t[nw]=1;
            return;
        }
        bild1(l,mid,ls);bild1(mid+1,r,rs);
        pu(nw);
    }
    void bild2(int l,int r,int nw){
        lz[nw]=0;
        if(l==r){
            if(a[l]<=num)t[nw]=0;
            else t[nw]=1;
            return;
        }
        bild2(l,mid,ls);bild2(mid+1,r,rs);
        pu(nw);
    }
    void modify(int l,int r,int s,int e,int nw,int op){
        if(l>r || r<s || l>e)return;
        if(s<=l && r<=e){
            if(op==1)t[nw]=r-l+1,lz[nw]=1;
            else t[nw]=0,lz[nw]=-1;
            return;
        }
        pd(l,r,nw);
        if(mid>=s)modify(l,mid,s,e,ls,op);
        if(mid<e)modify(mid+1,r,s,e,rs,op);
        pu(nw);
    }
    int sum(int l,int r,int s,int e,int nw){
        if(r<s || l>e || l>r)return 0;
        if(s<=l && r<=e)return t[nw];
        pd(l,r,nw);
        return sum(l,mid,s,e,ls)+sum(mid+1,r,s,e,rs);
    }
}t;
struct QQ{
    int c,l,r;
}q[N];
int Q;
int dy1[N],dy2[N];
void dy(int l,int r,int nw){
    if(l==r){dy1[l]=t.t[nw];return;}
    t.pd(l,r,nw);
    dy(l,mid,ls);
    dy(mid+1,r,rs);
}
void dyy(int l,int r,int nw){
    if(l==r){dy2[l]=t.t[nw];return;}
    t.pd(l,r,nw);
    dyy(l,mid,ls);
    dyy(mid+1,r,rs);
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(nullptr);
    cin>>n>>Q>>num;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=Q;i++)cin>>q[i].c>>q[i].l>>q[i].r;
    t.bild1(1,n,1);
    for(int i=1;i<=Q;i++){
        int cnt=t.sum(1,n,q[i].l,q[i].r,1);
        if(q[i].c==1){
            t.modify(1,n,q[i].l,q[i].r-cnt,1,0);
            t.modify(1,n,q[i].r-cnt+1,q[i].r,1,1);
        }
        else{
            t.modify(1,n,q[i].l,q[i].l+cnt-1,1,1);
            t.modify(1,n,q[i].l+cnt,q[i].r,1,0);
        }
    }
    dy(1,n,1);
    for(int i=0;i<N<<2;i++)t.t[i]=t.lz[i]=0;
    t.bild2(1,n,1);
    for(int i=1;i<=Q;i++){
        int cnt=t.sum(1,n,q[i].l,q[i].r,1);
        if(q[i].c==1){
            t.modify(1,n,q[i].l,q[i].r-cnt,1,0);
            t.modify(1,n,q[i].r-cnt+1,q[i].r,1,1);
        }
        else{
            t.modify(1,n,q[i].l,q[i].l+cnt-1,1,1);
            t.modify(1,n,q[i].l+cnt,q[i].r,1,0);
        }
    }
    dyy(1,n,1);
    for(int i=1;i<=n;i++){
        if(dy1[i]!=dy2[i]){
            cout<<i;
            return 0;
        }
    }
    cout<<-1;
    return 0;
} 
posted @   zxdjmq  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示