zoukankan      html  css  js  c++  java
  • 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);
        }
    }
  • 相关阅读:
    【转】i18n实现前端国际化(实例)
    【转】SQL Pretty Printer for SSMS 很不错的SQL格式化插件
    windows server IIS启用Windows authentication
    【转】命令行下载各种网上各种视频
    解决python “No module named pip”
    【转】excel音标乱码
    【转】自动化部署之jenkins及简介
    【转】右键菜单管理
    【转】C# @作用
    【转】NGen
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8397272.html
Copyright © 2011-2022 走看看