ABC237题解

2025-01-13 ABC237

F. |LIS|= 3

题意:

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

\(3\leq N \leq 1000,3\leq M \leq 10\)

解法:

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

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

\[\begin{cases} dp_{i+1,x,b,c} & x\leq a \\ dp_{i+1,a,x,c} & a<x \leq b \\ dp_{i+1,a,b,x} & b<x\leq c \end{cases} \]

最终答案即为\(\sum ^{m-2} _{a=1}\sum^{m-1}_{b=a+1}\sum^m_{c=b+1}dp_{n,a,b,c}\)


G. Range Sort Query

题意:

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

\(1\leq N,Q \leq 2\times 10^5\)

解法:

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

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

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

但是我们无法就此得到 \(X\) 的位置,所以我们把 \(0\) 的条件改为 \(\leq 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 @ 2025-01-13 15:36  zxdjmq  阅读(14)  评论(0)    收藏  举报