Problem C: 文体双花 解题报告

Problem C: 文体双花


被A穿的题,我这个屑只拿了20...

意识到这个题简单的时候考试已经快结束了,那边又各种吵,不过下午改题的情况来看,我可能码力还有点问题...

据神O所说,出这个题的时候没想到这个解法,然后考试的时候想到了...于是就成了真签到题


考虑到连续段的表示可以为\(r-l=mx-mi\),然后很显然可以dp一下就是\(dp_i\)代表前\(i\)的贡献然后枚举\(j\)转移,考虑用线段树优化这个转移即可。

具体的\(r\le mx+l-mi\),然后在线段树上移动指针,维护右边的最小值和最小值贡献。

\(mx\)\(mi\)的贡献在外面用单调栈维护一下就可以了。

还是要注意一下细节的


Code

#include <cstdio>
const int mod=1e9+7;
const int N=1e5+10;
#define add(a,b) (a+b>=mod?a+b-mod:a+b)
#define ls id<<1
#define rs id<<1|1
struct beecute
{
    int bee,sum;
    beecute friend operator +(beecute a,beecute b)
    {
        if(a.bee>b.bee) return b;
        if(a.bee==b.bee) a.sum=add(a.sum,b.sum);
        return a;
    }
}bee[N<<2];
int tag[N<<2],n,s0[N],s1[N],p[N],tot0,tot1;
void build(int id,int l,int r)
{
    int mid=l+r>>1;
    if(l^r) build(ls,l,mid),build(rs,mid+1,r),bee[id]=bee[ls]+bee[rs];
    else bee[id].bee=l,bee[id].sum=l==1;
}
void pushdown(int id)
{
    if(tag[id])
    {
        bee[ls].bee+=tag[id],bee[rs].bee+=tag[id];
        tag[ls]+=tag[id],tag[rs]+=tag[id];
        tag[id]=0;
    }
}
void modi(int id,int L,int R,int l,int r,int d)
{
    if(l==L&&r==R)
    {
        bee[id].bee+=d,tag[id]+=d;
        return;
    }
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) modi(ls,L,Mid,l,r,d);
    else if(l>Mid) modi(rs,Mid+1,R,l,r,d);
    else modi(ls,L,Mid,l,Mid,d),modi(rs,Mid+1,R,Mid+1,r,d);
    bee[id]=bee[ls]+bee[rs];
}
void ins(int id,int l,int r,int p,int d)
{
    if(l==r) {bee[id].sum=d;return;}
    pushdown(id);
    int mid=l+r>>1;
    if(p<=mid) ins(ls,l,mid,p,d);
    else ins(rs,mid+1,r,p,d);
    bee[id]=bee[ls]+bee[rs];
}
beecute query(int id,int l,int r,int p)
{
    if(r==p) return bee[id];
    pushdown(id);
    int mid=l+r>>1;
    if(p<=mid) return query(ls,l,mid,p);
    else return bee[ls]+query(rs,mid+1,r,p);
}
int main()
{
    scanf("%d",&n);
    build(1,1,n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",p+i);
        while(tot0&&p[s0[tot0]]<p[i])
        {
            modi(1,1,n,s0[tot0-1]+1,s0[tot0],p[i]-p[s0[tot0]]);
            --tot0;
        }
        s0[++tot0]=i;
        while(tot1&&p[s1[tot1]]>p[i])
        {
            modi(1,1,n,s1[tot1-1]+1,s1[tot1],p[s1[tot1]]-p[i]);
            --tot1;
        }
        s1[++tot1]=i;
        if(i<n) ins(1,1,n,i+1,query(1,1,n,i).sum);
    }
    printf("%d\n",query(1,1,n,n).sum);
    return 0;
}

2019.1.18

posted @ 2019-01-18 19:11  露迭月  阅读(223)  评论(0编辑  收藏  举报