zoukankan      html  css  js  c++  java
  • BZOJ3938:Robot

    浅谈标记永久化:https://www.cnblogs.com/AKMer/p/10137227.html

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3938

    首先,操作的个数小于等于(6*10^5),因为这个我对着我的程序干瞪眼白白浪费了半个晚上和半个早上。

    另外,由于是求离原点距离最远的,所以应该把所有的线段都移到(y)的正半轴上来。

    转化题意:对于(i)号机器人从第(x)秒到第(y)秒都按照(k)的速度移动,第(x)秒在(st),第(y)秒在(ed),我们可以算出一次函数的(b),然后在一次函数(y=kx+b)上面截取(x)(y)丢到李超线段树里去维护。

    最后,这题跟BZOJ3165:[HEOI2013]Segment基本一样。

    时间复杂度:(O(nlog^2n))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
     
    const int maxn=6e5+5;
     
    int n,m,cnt,tot;
    int pos[maxn],nxt[maxn],tim[maxn*4];
    int a[maxn],t[maxn],opt[maxn],id[maxn],x[maxn];
     
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
     
    struct Line {
        ll b;
        int st,ed,k;
     
        Line() {}
     
        Line(int _st,int _ed,ll _b,int _k) {
            st=_st,ed=_ed,b=_b,k=_k;
        }
    }line[maxn*4];
     
    struct segment_tree {
        int tag[maxn<<3];
     
        ll calc(int id,int x) {
            return line[id].b+1ll*x*line[id].k;
        }
     
        bool check(int id1,int id2,int x) {
            return calc(id1,x)<calc(id2,x);
        }
     
        ll query(int p,int l,int r,int pos) {
            if(l==r)return calc(tag[p],tim[l]);
            int mid=(l+r)>>1;ll ans=calc(tag[p],tim[pos]);
            if(pos<=mid)ans=max(ans,query(p<<1,l,mid,pos));
            else ans=max(ans,query(p<<1|1,mid+1,r,pos));
            return ans;
        }
     
        void change(int p,int l,int r,int id) {
            if(l==r) {
                if(check(tag[p],id,tim[l]))tag[p]=id;
                return;
            }
            int mid=(l+r)>>1;
            if(line[id].k>line[tag[p]].k) {
                if(check(tag[p],id,tim[mid]))change(p<<1,l,mid,tag[p]),tag[p]=id;
                else change(p<<1|1,mid+1,r,id);
            }
            else if(line[id].k==line[tag[p]].k) {
                if(check(tag[p],id,tim[mid]))tag[p]=id;
            }
            else {
                if(check(tag[p],id,tim[mid]))change(p<<1|1,mid+1,r,tag[p]),tag[p]=id;
                else change(p<<1,l,mid,id);
            }
        }
     
        void ins(int p,int l,int r,int L,int R,int id) {
            if(L<=l&&r<=R) {change(p,l,r,id);return;}
            int mid=(l+r)>>1;
            if(L<=mid)ins(p<<1,l,mid,L,R,id);
            if(R>mid)ins(p<<1|1,mid+1,r,L,R,id);
        }
        }T;
     
    void make_line(int l,int r,ll B,int K) {
        l=t[l],r=t[r];
        ll st=B,ed=B+1ll*K*(r-l);B=ed-1ll*r*K;
        if(st<=0&&ed<=0)line[++cnt]=Line(l,r,-B,-K);
        else if(st>=0&&ed>=0)line[++cnt]=Line(l,r,B,K);
        else {
            int T=(-B)/K;tim[++tot]=T;
            if(st>=0)line[++cnt]=Line(l,T,B,K),line[++cnt]=Line(T+1,r,-B,-K);
            else line[++cnt]=Line(l,T,-B,-K),line[++cnt]=Line(T+1,r,B,K);
        }
    }
     
    void solve_lines() {
        for(int i=1;i<=n;i++) {
            make_line(1,pos[i],a[i],0);
            int now=pos[i];ll B=a[i];
            while(now<m) {
                make_line(now,nxt[now],B,x[now]);
                B=B+1ll*x[now]*(t[nxt[now]]-t[now]);
                now=nxt[now];
            }
        }
    }
     
    int main() {
        n=read(),tot=m=read();
        for(int i=1;i<=n;i++)
            a[i]=read(),pos[i]=m;
        for(int i=1;i<=m;i++) {
            tim[i]=t[i]=read();
            char s[20];scanf("%s",s+1);
            if(s[1]=='q')opt[i]=1;
            else opt[i]=2;
            if(opt[i]==2)id[i]=read(),x[i]=read();
        }
        for(int i=m;i;i--)
            if(opt[i]==2)nxt[i]=pos[id[i]],pos[id[i]]=i;
        solve_lines();sort(tim+1,tim+tot+1);
        int num=unique(tim+1,tim+tot+1)-tim-1;
        tot=num;
        for(int i=1;i<=cnt;i++) {
            int l=lower_bound(tim+1,tim+tot+1,line[i].st)-tim;
            int r=lower_bound(tim+1,tim+tot+1,line[i].ed)-tim;
            T.ins(1,1,tot,l,r,i);
        }
        for(int i=1;i<=m;i++)
            if(opt[i]==1) {
                int q=lower_bound(tim+1,tim+tot+1,t[i])-tim;
                printf("%lld
    ",T.query(1,1,tot,q));
            }
        return 0;
    }
    
  • 相关阅读:
    第9天 图片整合
    第六天 元素类型
    第五天 文本溢出
    第四天 盒子模型
    第三天 css核心属性
    第二天 css基础 ,部分选择符
    第一天 HTML基础
    *Move Zeroes
    Word Pattern
    ReentrantLock
  • 原文地址:https://www.cnblogs.com/AKMer/p/10166817.html
Copyright © 2011-2022 走看看