• NOIP 模拟 $18; m 老司机的狂欢$


    题解 (by;zjvarphi)

    一道很有趣的题,我用的动态开点线段树和倍增

    首先对于第一问,不难想到要二分,二分时间,因为时间长一定不会比时间短能跑的人多

    那么如何 check,先将所有老司机按初始坐标排个序,之后将每个老司机跑的距离加上,那么就是对之后的序列求一个 ( m LIS)

    求这个长度可以用树装数组维护值域,而求这个字典序最小的序列就需要用到倍增;类似于树上倍增,对于 (i,j) 的序列,他们在相同的一位之前一定是一样的,而之后哪个的最小值小,那个就更优

    我们对于序列长度开一棵动态开点线段树,每个节点存的是这一段位置的最优选择,每次回溯时维护即可

    复杂度就是 (mathcal O( m nlognlogt+nlog^2n))

    Code
    #include<bits/stdc++.h>
    #define ri register signed
    #define p(i) ++i
    using namespace std;
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
        template<typename T>inline void read(T &x) {
            ri f=1;x=0;register char ch=gc();
            while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
            while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
            x=f?x:-x;
        }
    }
    using IO::read;
    namespace nanfeng{
        #define FI FILE *IN
        #define FO FILE *OUT
        template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
        template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
        typedef long long ll;
        typedef double db;
        static const int N=1e5+7;
        struct node{ll pos;int a,id;}dr[N];
        int p[N],pi[N],pre[N][21],mn[N][21],tpr[N],dp[N],num,n,k,ed;
        db pos[N],tmp[N];
        priority_queue<int,vector<int>,greater<int> > quea;
        inline int operator<(const node &n1,const node &n2) {return n1.pos<n2.pos;}
        inline int cmp(int x,int y) {return pos[x]<pos[y];}
        struct BIT{
            #define lowbit(x) ((x)&-(x))
            int c[N];
            inline void update(int x,int len) {
                for (ri i(x);i<=n;i+=lowbit(i)) c[i]=cmax(c[i],len);
            }
            inline int query(int x) {
                int res=0;
                if (!x) return res;
                for (ri i(x);i;i-=lowbit(i)) res=cmax(res,c[i]);
                return res;
            }
        }B;
        struct Seg{
            #define ls(x) T[x].l
            #define rs(x) T[x].r
            struct segmenttree{int l,r,cur;}T[N*21];
            int rt[N],tot;
            inline int calc(int x1,int x2) {
                ri mn1=INT_MAX,mn2=INT_MAX;
                ri tx1=x1,tx2=x2;
                for (ri i(17);~i;--i) 
                    if (pre[x1][i]!=pre[x2][i]) {
                        mn1=cmin(mn1,mn[x1][i]),mn2=cmin(mn2,mn[x2][i]);
                        x1=pre[x1][i],x2=pre[x2][i];
                    }
                mn1=cmin(mn1,mn[x1][0]),mn2=cmin(mn2,mn[x2][0]);
                if (mn1<mn2) return tx1;
                else return tx2;
            } 
            inline void up(int x) {
                if (!ls(x)) T[x].cur=T[rs(x)].cur;
                else if (!rs(x)) T[x].cur=T[ls(x)].cur;
                else {
                    ri x1=T[ls(x)].cur,x2=T[rs(x)].cur;
                    T[x].cur=calc(x1,x2);
                }
            }
            void update(int &x,int k,int p,int l,int r) {
                if (!x) x=p(tot);
                if (l==r) return (void)(T[x].cur=k);
                int mid(l+r>>1);
                if (p<=mid) update(ls(x),k,p,l,mid);
                else update(rs(x),k,p,mid+1,r);
                up(x);
            }
            int query(int x,int l,int r,int lt,int rt) {
                if (!x) return 0;
                if (l<=lt&&rt<=r) return T[x].cur;
                int mid(lt+rt>>1),tmp1(0),tmp2(0);
                if (l<=mid) tmp1=query(ls(x),l,r,lt,mid);
                if (r>mid) tmp2=query(rs(x),l,r,mid+1,rt);
                if (!tmp1||!tmp2) return (tmp1|tmp2);
                return calc(tmp1,tmp2);
            }
            int tst(int x,int p,int l,int r) {
                if (!x) return 0;
                if (l==r) return T[x].cur;
                int mid(l+r>>1);
                if (p<=mid) return tst(ls(x),p,l,mid); 
                else return tst(rs(x),p,mid+1,r);
            }
        }T;
        inline int check(int tim) {
            num=0;
            memset(B.c,0,sizeof(B.c));
            memset(dp,0,sizeof(dp));
            for (ri i(1);i<=n;p(i)) pos[i]=0.5*(db)dr[i].a*tim*(db)tim+(db)dr[i].pos,tmp[i]=pos[i];
            sort(tmp+1,tmp+n+1);
            ri kk=unique(tmp+1,tmp+n+1)-tmp;
            for (ri i(1);i<=n;p(i)) pi[i]=lower_bound(tmp+1,tmp+kk,pos[i])-tmp;
            for (ri i(1);i<=n;p(i)) {
                ri cur=p[i],curp=pi[i];
                int res=B.query(curp-1);
                if (res+1>num) num=res+1;
                dp[i]=res+1;
                B.update(curp,res+1);
            }
            if (num>=k) return 1;
            return 0;
        }
        inline int main() {
            // FI=freopen("nanfeng.in","r",stdin);
            // FO=freopen("nanfeng.out","w",stdout);
            read(n),read(k);
            for (ri i(1);i<=n;p(i)) read(dr[i].pos),read(dr[i].a),dr[i].id=i;
            sort(dr+1,dr+n+1);
            for (ri i(1);i<=n;p(i)) p[i]=dr[i].id;
            ri l=0,r=86400,ans;
            while(l<=r) {
                int mid(l+r>>1);
                if (check(mid)) l=mid+1,ans=mid;
                else r=mid-1;
            }
            check(ans);
            printf("%d
    ",ans);
            if (num>k) puts("-1");
            else {
                memset(mn,0x3f,sizeof(mn));
                for (ri i(1);i<=n;p(i)) {
                    ri cur=p[i];
                    mn[cur][0]=cur;
                    if (dp[i]-1>0) {
                        pre[cur][0]=T.query(T.rt[dp[i]-1],1,pi[i]-1,1,n);
                        for (ri j(1);j<=17;p(j)) {
                            mn[cur][j]=cmin(mn[cur][j-1],mn[pre[cur][j-1]][j-1]);
                            pre[cur][j]=pre[pre[cur][j-1]][j-1];
                        }
                    }
                    T.update(T.rt[dp[i]],cur,pi[i],1,n);
                }
                ri cur=T.query(T.rt[num],1,n,1,n); 
                while(pre[cur][0]) quea.push(cur),cur=pre[cur][0];                
                quea.push(cur);
                while(!quea.empty()) printf("%d
    ",quea.top()),quea.pop();    
            }
            return 0;
        }  
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    【MariaDB】MariaDB的复制
    【MariaDB】MariaDB编译参数
    【MySQL】MySQL锁和隔离级别浅析二 之 INSERT
    【MySQL】查询使用临时表
    【MySQL】使用mysqlbinlog回滚
    ELK学习笔记(三)单台服务器多节点部署
    ELK学习笔记(二)-HelloWorld实例+Kibana介绍
    ELK学习笔记(六)分布式集群
    ELK学习笔记(四)SpringBoot+Logback+Redis+ELK实例
    ELK学习笔记(一)安装Elasticsearch、Kibana、Logstash和X-Pack
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15028936.html
Copyright © 2020-2023  润新知