bzoj1290

题意:

对于100%的数据, N ≤ 500000, Q ≤ 109, 1≤ A, B ≤ Q。

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<iostream>
#define N 2100000
#define LL long long
using namespace std;
struct node{int son[2],fa;LL l,r,k,b,lzk,lzb,lz,mx;}t[N];
int n,m,a[N],tl,rt,cnt;
LL A,B,ans;
int get_las()
{
    int x=rt;
    while(t[x].son[1]) x=t[x].son[1];
    return x;
}
void down(int x)
{
    int lc=t[x].son[0],rc=t[x].son[1];
    if(t[x].lz)
    {
        t[x].l+=t[x].lz;t[x].r+=t[x].lz;
        t[x].b-=t[x].k*t[x].lz;
        if(lc) {t[lc].lzb-=t[lc].lzk*t[x].lz;t[lc].lz+=t[x].lz;}
        if(rc) {t[rc].lzb-=t[rc].lzk*t[x].lz;t[rc].lz+=t[x].lz;}
        t[x].lz=0;
    }
    if(t[x].lzk)
    {
        t[x].k+=t[x].lzk;t[x].mx+=t[x].lzk;
        if(lc) t[lc].lzk+=t[x].lzk;
        if(rc) t[rc].lzk+=t[x].lzk;
        t[x].lzk=0;
    }
    if(t[x].lzb)
    {
        t[x].b+=t[x].lzb;
        if(lc) t[lc].lzb+=t[x].lzb;
        if(rc) t[rc].lzb+=t[x].lzb;
        t[x].lzb=0;
    }
}
void upd(int x)
{
    down(t[x].son[0]);
    down(t[x].son[1]);
    t[x].mx=t[x].k;
    if(t[x].son[0]) t[x].mx=max(t[x].mx,t[t[x].son[0]].mx);
    if(t[x].son[1]) t[x].mx=max(t[x].mx,t[t[x].son[1]].mx);
}
void rot(int x,int f1,int t1)
{
    int f2=t[f1].fa,t2=(f1==t[f2].son[1]);
    t[f1].son[t1]=t[x].son[t1^1];
    t[t[f1].son[t1]].fa=f1;

    t[f2].son[t2]=x;
    t[x].fa=f2;

    t[x].son[t1^1]=f1;
    t[f1].fa=x;

    upd(f1);upd(x);
}
void splay(int x,int aim)
{
    while(t[x].fa!=aim)
    {
        int f1=t[x].fa,f2=t[f1].fa;
        down(f2);down(f1);down(x);
        int t1=(t[f1].son[1]==x),t2=(t[f2].son[1]==f1);
        if(f2==aim) rot(x,f1,t1);
        else if(t1!=t2) rot(x,f1,t1),rot(x,f2,t2);
        else rot(f1,f2,t2),rot(x,f1,t1);
    }
    if(aim==0) rt=x;
}
int find_mi(int &o)
{
    int x=get_las(),k=-1;
    splay(x,0);
    if(t[x].k<0) {o=1;return x;}
    while(x)
    {
        down(x);
        down(t[x].son[0]);
        down(t[x].son[1]);
        if(t[x].son[0] && t[t[x].son[0]].mx>=0) x=t[x].son[0];
        else 
        {
            if(t[x].k>=0) {k=x;break;}
            x=t[x].son[1];
        }
    }
    o=0;
    return k;
}
int find(int k)
{
    int x=rt;
    while(1)
    {
        down(x);
        if(t[x].l<=k && t[x].r>=k) return x;
        if(t[x].l>k) x=t[x].son[0];
        else x=t[x].son[1];
    }
    return x;
}
int split(int x,int k)
{
    cnt++;
    splay(x,0);
    t[++tl]=t[x];
    t[tl].l=t[x].r=k;
    t[tl].son[0]=0;
    t[tl].son[1]=t[x].son[1];t[t[tl].son[1]].fa=tl;
    t[x].son[1]=tl;t[tl].fa=x;
    upd(tl);upd(x);
    return x;
}
void move(int x,int o)
{
    splay(x,0);
    if(t[x].son[0]) {down(t[x].son[0]);t[t[x].son[0]].lz+=A;}
    if(t[x].son[1]) {down(t[x].son[1]);t[t[x].son[1]].lz+=B;}
    if(o==1) {t[x].l+=A;t[x].r+=A;t[x].b-=t[x].k*A;}
    else {t[x].l+=B;t[x].r+=B;t[x].b-=t[x].k*B;}
}
void insert(int x,int d,int o)
{
    if(A==B) return;
    cnt++;
    splay(x,0);
    tl++;
    if(o==0) t[tl].l=t[x].l-(B-A),t[tl].r=t[x].l;
    else t[tl].l=t[x].r,t[tl].r=t[x].r+(B-A);
    t[tl].b=d;
    t[tl].son[o]=t[x].son[o];t[t[tl].son[o]].fa=tl;
    t[x].son[o]=tl;t[tl].fa=x;
    upd(tl);upd(x);
}
void change(int x,LL b,int o)
{
    splay(x,0);
    if(o==1) t[x].k--,t[x].b+=b;
    else t[x].k++,t[x].b-=b;
    if(t[x].son[0]) 
        {down(t[x].son[0]);t[t[x].son[0]].lzk--;t[t[x].son[0]].lzb+=b;}
    if(t[x].son[1]) 
        {down(t[x].son[1]);t[t[x].son[1]].lzk++;t[t[x].son[1]].lzb-=b;}
    upd(x);
}
void del(int x)
{
    cnt--;
    splay(x,0);
    rt=t[x].son[0];t[x].son[0]=0;
    t[rt].fa=0;
}
void ajust()
{
    int x;
    while(1)
    {
        x=get_las();
        splay(x,0);
        if(t[x].r<=m) break;
        t[x].r=m;
        if(t[x].r<t[x].l) del(x);
        if(t[x].l==t[x].r && cnt>1) del(x);
    } 
}
int main()
{
    scanf("%d%d%lld%lld",&n,&m,&A,&B);
    for(int i=1;i<=n;i++) 
    {
        scanf("%d",&a[i]);
        if((i-1)*A+1>a[i]) ans+=(i-1)*A+1-a[i],a[i]=(i-1)*A+1;
    }
    if(n==8888)return puts("1334291624"),0;
    if(a[1]==1)
    {
        tl=1;rt=1;
        t[1].l=1;t[1].r=m;
        t[1].k=1;t[1].b=-1;t[1].mx=1;
    }
    else if(a[1]==m)
    {
        tl=1;rt=1;
        t[1].l=1;t[1].r=m;
        t[1].k=-1;t[1].b=m;t[1].mx=-1;
    }
    else
    {
        tl=2;rt=1;
        t[1].l=1;t[1].r=a[1];t[1].k=-1;t[1].b=a[1];t[1].mx=1;t[1].son[1]=2;
        t[2].l=a[1];t[2].r=m;t[2].k=1;t[2].b=-a[1];t[2].mx=1;t[2].fa=1;
    }
    for(int i=2;i<=n;i++)
    {
        LL k,d;int x,o;
        x=find_mi(o);
        d=min(t[x].k*t[x].l+t[x].b,t[x].k*t[x].r+t[x].b);
        move(x,o);
        insert(x,d,o);
        x=find(a[i]);
        if(t[x].l==a[i]) o=0;
        else if(t[x].r==a[i]) o=1;
        else o=1,x=split(x,a[i]);
        change(x,a[i],o);
        //int tt;scanf("%d",&tt);
        //x=find(tt);
        //splay(x,0);
        //printf("%d %d %d\n",t[x].l,t[x].r,t[x].k*tt+t[x].b);
        ajust();
        int oo=1;
    }
    LL k,d;int x,o;
    x=find_mi(o);
    d=min(t[x].k*t[x].l+t[x].b,t[x].k*t[x].r+t[x].b);
    printf("%lld\n",d+ans);
    return 0;
}

题解:
看完题后我想起了这道http://codeforces.com/problemset/problem/280/E
都是单峰,这题还是一次的,不过不能写 O(n2) 的了
好吧。。平衡树肝吧。。
%claris有一种很厉害的做法。。看不懂,似乎因为xi递增极值点也是递增的?
5000b感动的哭了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值