XUANMING'S JOURNAL屏幕在深夜微微发亮,我心在远方。
← 回到笔记
FIELD NOTES

题解 P6812 【「MCOI-02」Ancestor 先辈】

线段树入门题。

题意很清晰,通过观察屑的定义,可以发现先辈有如下性质:

​ 对于长度为$n$序列$a$,如果它是先辈,那么它满足:

​ $a_1\le a_2\le a_3 \cdots\le a_n$

为什么呢?通过观察,我们发现先辈的后缀中除了它自己外,它的最长后缀的需要满足的关系最强(即如上性质),而其他后缀需要满足的关系是它的子集,比如第二长的后缀需要满足的关系是$a_1\le a_3, a_2\le a_4 \cdots$,显然更弱,所以说问题转化成了:

  1. 区间加
  2. 询问一个区间是否单调上升

然后变成了线段树裸题。

具体做法:线段树维护区间左端点的值$lv$,区间右端点的值$rv$,区间是否是先辈。$pushup$时,如果一段区间的左右儿子都是先辈,并且左儿子的$rv$小于等于右儿子的$lv$,则这段区间是先辈,询问同理。

不要试图抄我的代码,直接交会$wa$一个点

代码(很短的):

inline void update(int u,ll k)
{
    tr[u].lv+=k;tr[u].rv+=k;tr[u].la+=k;
}

inline void pushup(Node &u,const Node &a,const Node &b)
{
    u.lv=a.lv;u.rv=b.rv;
    u.is=a.is&&b.is&&(a.rv<b.lv);
}

inline void pushdown(int u)
{
    if(!tr[u].la) return;
    update(u<<1,tr[u].la);update(u<<1|1,tr[u].la);
    tr[u].la=0;
}

void build(int u,int l,int r)
{
    if(l==r) {tr[u].lv=tr[u].rv=a[l];tr[u].is=1;return;}
    int mid=(l+r)>>1;
    build(u<<1,l,mid);build(u<<1|1,mid+1,r);
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}

void modify(int u,int l,int r,int x,int y,ll val)
{
    if(x<=l&&r<=y) return update(u,val);
    int mid=(l+r)>>1;
    pushdown(u);
    if(x<=mid) modify(u<<1,l,mid,x,y,val);
    if(y>mid) modify(u<<1|1,mid+1,r,x,y,val);
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}

Node query(int u,int l,int r,int x,int y)
{
    if(x<=l&&r<=y) return tr[u];
    int mid=(l+r)>>1;
    pushdown(u);
    if(y<=mid) return query(u<<1,l,mid,x,y);
    if(x>mid) return query(u<<1|1,mid+1,r,x,y);
    Node ans;pushup(ans,query(u<<1,l,mid,x,y),query(u<<1|1,mid+1,r,x,y));
    return ans;
}

template<typename T>
inline void read(T &x)
{
    char c;int f=1;
    while(!isdigit(c=getchar())) (c=='-')&&(f=-1);
    x=c^48;
    while(isdigit(c=getchar())) x=x*10+(c^48);
    x*=f;
}

int main()
{
    int t,opt,x,y;
    ll val;
    read(n);read(t);
    for(int i=1;i<=n;++i) read(a[i]);
    build(1,1,n);
    while(t--)
    {
        read(opt);read(x);read(y);
        if(opt==1) read(val),modify(1,1,n,x,y,val);
        else printf("%s\n",query(1,1,n,x,y).is?"Yes":"No");
    }
    return 0;
}

输入关键词,搜索全部笔记。