[JSOI2009]等差数列

[JSOI2009]等差数列

https://ac.nowcoder.com/acm/problem/20177

思路

对于这题,首先要知道维护一些什么东西.
我们都知道区间加个等差数列,假如维护单点求和的话,直接维护公差即可.因为区间加一个等差数列只需要两次单点修改和一次区间修改即可.
对于这题,我们很容易想到维护公差.但是对于查询操作维护公差是远远不够的.每次是询问你区间中有多少个等差数列.对于这个查询啊,我们假如线段树维护的是公差的话,我们很容易想到公差相等的一定是属于一个等差数列,但是!我们维护的是公差对吧,公差不相等它也可能是一个等差数列.
列如:

原数组[1 2 3 6 11 16].
公差数组[1 1 3 5 5].

显然这个答案是2的.
所以我们需要维护的信息需要加一些.

我们不妨设为cl,cr,clr,nlr,lval,rval.
分别表示为[l,r),(l,r],[l,r],(l,r)的答案最小值.左端点的价值,右端点的价值.

然后转移下这些信息就是答案了~这题就解决了...
这里写下这个的转移.

tr[u].lval=tr[u<<1].lval,tr[u].rval=tr[u<<1|1].rval;
tr[u].cl=tr[u<<1].clr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].cl=min(tr[u].cl,min(tr[u<<1].cl+tr[u<<1|1].cl,tr[u<<1].clr+tr[u<<1|1].nlr));
tr[u].cr=tr[u<<1].cr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].cr=min(tr[u].cr,min(tr[u<<1].cr+tr[u<<1|1].cr,tr[u<<1].nlr+tr[u<<1|1].clr));
tr[u].clr=tr[u<<1].clr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].clr=min(tr[u].clr,min(tr[u<<1].clr+tr[u<<1|1].cr,tr[u<<1].cl+tr[u<<1|1].clr));
tr[u].nlr=tr[u<<1].cr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].nlr=min(tr[u].nlr,min(tr[u<<1].nlr+tr[u<<1|1].cl,tr[u<<1].cr+tr[u<<1|1].nlr));

还挺多的...

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct Tree{
    ll l,r,lval,rval,cl,cr,clr,nlr,lazy;
}tr[N<<2];
ll v[N];

void pushup(ll u)
{
    tr[u].lval=tr[u<<1].lval,tr[u].rval=tr[u<<1|1].rval;
    tr[u].cl=tr[u<<1].clr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval);
    tr[u].cl=min(tr[u].cl,min(tr[u<<1].cl+tr[u<<1|1].cl,tr[u<<1].clr+tr[u<<1|1].nlr));
    tr[u].cr=tr[u<<1].cr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval);
    tr[u].cr=min(tr[u].cr,min(tr[u<<1].cr+tr[u<<1|1].cr,tr[u<<1].nlr+tr[u<<1|1].clr));
    tr[u].clr=tr[u<<1].clr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval);
    tr[u].clr=min(tr[u].clr,min(tr[u<<1].clr+tr[u<<1|1].cr,tr[u<<1].cl+tr[u<<1|1].clr));
    tr[u].nlr=tr[u<<1].cr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval);
    tr[u].nlr=min(tr[u].nlr,min(tr[u<<1].nlr+tr[u<<1|1].cl,tr[u<<1].cr+tr[u<<1|1].nlr));
}

void pushdown(ll u)
{
    if(tr[u].lazy)
    {
        tr[u<<1].lazy+=tr[u].lazy;
        tr[u<<1|1].lazy+=tr[u].lazy;
        tr[u<<1].lval+=tr[u].lazy;
        tr[u<<1|1].lval+=tr[u].lazy;
        tr[u<<1].rval+=tr[u].lazy;
        tr[u<<1|1].rval+=tr[u].lazy;
        tr[u].lazy=0;
    }
}

void add(ll u,ll l,ll r,ll val)
{
    if(l>tr[u].r||r<tr[u].l)    return;
    if(l<=tr[u].l&&r>=tr[u].r)
    {
        tr[u].lazy+=val;
        tr[u].lval+=val;
        tr[u].rval+=val;
        return;
    }
    pushdown(u);
    add(u<<1,l,r,val);
    add(u<<1|1,l,r,val);
    pushup(u);
}

Tree query(ll u,ll l,ll r);

Tree marge(ll u,ll l,ll r)
{
    Tree res;
    Tree L=query(u<<1,l,r);
    Tree R=query(u<<1|1,l,r);
    res.l=L.l,res.r=R.r,res.lval=L.lval,res.rval=R.rval;
    res.cl=L.clr+R.cl-(L.rval==R.lval);
    res.cl=min(res.cl,min(L.cl+R.cl,L.clr+R.nlr));
    res.cr=L.cr+R.clr-(L.rval==R.lval);
    res.cr=min(res.cr,min(L.cr+R.cr,L.nlr+R.clr));
    res.clr=L.clr+R.clr-(L.rval==R.lval);
    res.clr=min(res.clr,min(L.clr+R.cr,L.cl+R.clr));
    res.nlr=L.cr+R.cl-(L.rval==R.lval);
    res.nlr=min(res.nlr,min(L.nlr+R.cl,L.cr+R.nlr));
    return res;
}

Tree query(ll u,ll l,ll r)
{
    if(l<=tr[u].l&&r>=tr[u].r)    return tr[u];
    pushdown(u);
    ll mid=(tr[u].l+tr[u].r)>>1;
    if(r<=mid)    return query(u<<1,l,r);
    if(l>mid)     return query(u<<1|1,l,r);
    return marge(u,l,r);
}

void build(ll u,ll l,ll r)
{
    tr[u].l=l,tr[u].r=r;
    if(l==r)
    {
        tr[u].lval=tr[u].rval=v[l];
        tr[u].cl=tr[u].cr=tr[u].clr=1;
        return;
    }
    int mid=(l+r)>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    pushup(u);
}

int main()
{
    ll n;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)    scanf("%lld",&v[i]);
    for(int i=1;i<n;i++)    v[i]=v[i+1]-v[i];
    build(1,1,n-1);
    ll Q;
    scanf("%lld",&Q);
    while(Q--)
    {
        char c;
        cin>>c;
        if(c=='A')
        {
            ll s,t,a,b;
            scanf("%lld%lld%lld%lld",&s,&t,&a,&b);
            //s-1 [s,t-1] t
            if(s!=1)        add(1,s-1,s-1,a);
            if(t!=n)    add(1,t,t,-(a+b*(t-s)));
            if(s!=t)    add(1,s,t-1,b);
        }
        else
        {
            ll s,t;
            scanf("%lld%lld",&s,&t);
            if(s==t)    puts("1");
            else        printf("%lld\n",query(1,s,t-1).clr);
        }
    }
    return 0;
}
lpt的小屋 文章被收录于专栏

我想要一份甜甜的爱情

全部评论

相关推荐

废铁汽车人:秋招真是牛鬼蛇神齐聚一堂
点赞 评论 收藏
分享
Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
4 收藏 评论
分享
牛客网
牛客企业服务