bzoj千题计划220:bzoj3938: Robot

http://www.lydsy.com/JudgeOnline/problem.php?id=3938

以时间为x轴,以距离为y轴,那么每个机器人的行走路径就是一条折线

把折线分段加入线段树里,然后就是线段树维护单点一次函数最大值和最小值

调了半下午+一晚上一直在TTT

今早突然发觉,

之前用来贡献最大值的一次函数和最小值的一次函数都放在了一颗线段树里

下传的时候,同时更新最大值和最小值,

导致只需要更新最小值的一次函数的时候也更新了最大值的一次函数

由于永久标记虽然不会出错,但过多的下放标记浪费了时间

改成两颗线段树,马上就A了

我算不算体验到了 昏天黑地调代码一直TTT一觉起来灵机一动就A了的 激动???

要不是在学校机房我就大叫了,哈哈哈哈哈哈哈哈哈哈哈

#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>

using namespace std;

typedef long long LL;

#define N 100001

struct node
{
    int t,v;
    node(int t=0,int v=0):t(t),v(v) {}
}e[N*3];

int cnt,nxt[N*3],ed[N]; 

int q[N*5];
LL pos[N];

int root,tot;
int ROOT,TOT;

struct TREE
{
    int mxA;
    int lc,rc;
    LL mxB;
}TR[N*30];

struct tree
{
    int miA;
    int lc,rc;
    LL miB;
}tr[N*30];

LL ans;

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

void DOWN(int &k,int l,int r,int a,LL b)
{
    if(!k) k=++TOT;
    int mid=l+r>>1;
    if(!TR[k].mxA && !TR[k].mxB)
    {
        TR[k].mxA=a;
        TR[k].mxB=b;
    }
    else if(l==r) TR[k].mxB=max(TR[k].mxB,b);
    else
    {
        LL minow,mipre,mxnow,mxpre;
        minow=min(b,1LL*(r-l)*a+b);
        mxnow=max(b,1LL*(r-l)*a+b);
        mipre=min(TR[k].mxB,1LL*(r-l)*TR[k].mxA+TR[k].mxB);
        mxpre=max(TR[k].mxB,1LL*(r-l)*TR[k].mxA+TR[k].mxB);
        if(minow>=mxpre)
        {
            TR[k].mxA=a;
            TR[k].mxB=b;
        }
        else if(mipre>=mxnow);
        else if(1LL*a*(mid-l)+b>1LL*TR[k].mxA*(mid-l)+TR[k].mxB)
        {
            if(TR[k].mxB>b) DOWN(TR[k].lc,l,mid,TR[k].mxA,TR[k].mxB);
            else DOWN(TR[k].rc,mid+1,r,TR[k].mxA,1LL*(mid+1-l)*TR[k].mxA+TR[k].mxB);
            TR[k].mxA=a; 
            TR[k].mxB=b;
        }
        else 
        {
            if(TR[k].mxB>b) DOWN(TR[k].rc,mid+1,r,a,1LL*a*(mid+1-l)+b); 
            else DOWN(TR[k].lc,l,mid,a,b);
        }
    }
}

void down(int &k,int l,int r,int a,LL b)
{
    if(!k) k=++tot;
    int mid=l+r>>1;
    if(!tr[k].miA && !tr[k].miB)
    {
        tr[k].miA=a;
        tr[k].miB=b;
    }
    else if(l==r) tr[k].miB=min(tr[k].miB,b);
    else
    {
        LL minow,mipre,mxnow,mxpre;
        minow=min(b,1LL*(r-l)*a+b);
        mxnow=max(b,1LL*(r-l)*a+b);
        mipre=min(tr[k].miB,1LL*(r-l)*tr[k].miA+tr[k].miB);
        mxpre=max(tr[k].miB,1LL*(r-l)*tr[k].miA+tr[k].miB);
        if(mxnow<=mipre)
        {
            tr[k].miA=a;
            tr[k].miB=b;
        }
        else if(mxpre<=minow);
        else if(1LL*a*(mid-l)+b>1LL*tr[k].miA*(mid-l)+tr[k].miB)
        {
            if(tr[k].miB<b) down(tr[k].rc,mid+1,r,a,1LL*(mid+1-l)*a+b);
            else down(tr[k].lc,l,mid,a,b);
        }
        else 
        {
            if(tr[k].miB<b) down(tr[k].lc,l,mid,tr[k].miA,tr[k].miB);
            else down(tr[k].rc,mid+1,r,tr[k].miA,1LL*tr[k].miA*(mid+1-l)+tr[k].miB); 
            tr[k].miA=a; 
            tr[k].miB=b;
        }
    }
}

void CHANGE(int &k,int l,int r,int opl,int opr,int a,LL b)
{
    if(!k) k=++TOT;
    if(l==opl && r==opr)
    {
        DOWN(k,l,r,a,b);
        return;
    }
    int mid=l+r>>1;
    if(opr<=mid) CHANGE(TR[k].lc,l,mid,opl,opr,a,b);
    else if(opl>mid) CHANGE(TR[k].rc,mid+1,r,opl,opr,a,b);
    else
    {
        CHANGE(TR[k].lc,l,mid,opl,mid,a,b);
        CHANGE(TR[k].rc,mid+1,r,mid+1,opr,a,1LL*(mid+1-opl)*a+b);
    }
}

void change(int &k,int l,int r,int opl,int opr,int a,LL b)
{
    if(!k) k=++tot;
    if(l==opl && r==opr)
    {
        down(k,l,r,a,b);
        return;
    }
    int mid=l+r>>1;
    if(opr<=mid) change(tr[k].lc,l,mid,opl,opr,a,b);
    else if(opl>mid) change(tr[k].rc,mid+1,r,opl,opr,a,b);
    else
    {
        change(tr[k].lc,l,mid,opl,mid,a,b);
        change(tr[k].rc,mid+1,r,mid+1,opr,a,1LL*(mid+1-opl)*a+b);
    }
}

void QUERY(int k,int l,int r,int pos)
{
    if(!k) return;
    if(l==r)
    {
        ans=max(ans,TR[k].mxB);
        return;
    }
    ans=max(ans,1LL*(pos-l)*TR[k].mxA+TR[k].mxB);
    int mid=l+r>>1;
    if(pos<=mid) QUERY(TR[k].lc,l,mid,pos);
    else QUERY(TR[k].rc,mid+1,r,pos);
}

void query(int k,int l,int r,int pos)
{
    if(!k) return;
    if(l==r)
    {
        ans=max(ans,-tr[k].miB);
        return;
    }
    ans=max(ans,-(1LL*(pos-l)*tr[k].miA+tr[k].miB));
    int mid=l+r>>1;
    if(pos<=mid) query(tr[k].lc,l,mid,pos);
    else query(tr[k].rc,mid+1,r,pos);
}

int main()
{
    //freopen("data.in","r",stdin);
    //freopen("my.out","w",stdout);
    int n,m,k,x,t;
    char s[8];
    read(n); read(m);
    for(int i=1;i<=n;++i) 
    {
         read(pos[i]);
         ed[i]=i;
         e[i].t=0;
         e[i].v=0;
    }
    cnt=n;
    int sum=0;
    int last;
    while(m--)
    {
        read(t);
        scanf("%s",s);
        if(s[0]=='q') q[++sum]=t;
        else
        {
            read(k); read(x);
            e[++cnt].v=x; e[cnt].t=t;
            nxt[ed[k]]=cnt;
            ed[k]=cnt;
        }
        last=t;
    }
    for(int i=1;i<=n;++i) 
    {
        e[++cnt].t=last;
        e[cnt].v=0;
        nxt[ed[i]]=cnt;
        ed[i]=cnt;
    }
    int siz;
    for(int i=1;i<=n;++i)
    {
        int j;
        for(j=i;j!=ed[i];j=nxt[j]) 
        {
            CHANGE(ROOT,0,last,e[j].t,e[nxt[j]].t,e[j].v,pos[i]);
            change(root,0,last,e[j].t,e[nxt[j]].t,e[j].v,pos[i]);
            pos[i]+=1LL*(e[nxt[j]].t-e[j].t)*e[j].v;
        }
    }
    for(int i=1;i<=sum;++i)
    {
        ans=0;
        QUERY(ROOT,0,last,q[i]);
        query(root,0,last,q[i]);
        printf("%lld
",ans);
    }
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8397272.html