• 20191015+


    前言

    • 连第二机房房主也不是了,该高兴还是该呵呵?
    • 板子不会还是硬伤,不会高斯消元的我看到T2都绝望了,YY还写错了……
    • T3特判都打错,佛啦。
    • 咳咳。还有为什么还是这么颓废。
    • 还有%%%文化课巨佬FlashHu

    以上纯属CD。

    T1

    • 先把(a,b)按a单调下降排序,然后将不符合b单调上升的点删除,因为这些点不可能成为答案。
    • 然后将给出的(a,b)抽象成$(frac{1}{a},frac{1}{b})$的点,因为a单调下降b单调上升所以新点集的横坐标单调上升纵坐标单调递减。
    • 直接用栈维护左下凸包,栈内斜率单调递增即可。
    • 时间复杂度$Theta(NlogN)$,空间复杂度$Theta(N)$。
    • 本题精度稍GS,蒟蒻博主的垃圾代码开__float128才能AC……
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #define ll long long
    #define db __float128
    using namespace std;
    typedef pair<pair<int,int>,int> pi;
    int const N=3e5+5;
    db const lar=2e16,eps=-1e-6;
    int n,t;
    pi b[N];
    pair<int,int>a[N];
    vector<int>bs[N];
    int ans[N];
    int stk[N],tp;
    db xp[N],yp[N],xl[N];
    inline int read(){
        int ss(0);char bb(getchar());
        while(bb<48||bb>57)bb=getchar();
        while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
        return ss;
    }
    inline db _max(db x,db y){
        return x>y?x:y;
    }
    inline db _min(db x,db y){
        return x<y?x:y;
    }
    int main(){
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        n=read();
        for(register int i=1;i<=n;++i)b[i].first.first=read(),b[i].first.second=read(),b[i].second=i;
        sort(b+1,b+n+1,[](pi skyh,pi yxs){
            return (skyh.first.first^yxs.first.first)?skyh.first.first>yxs.first.first:skyh.first.second>yxs.first.second;
        });
        for(register int i=1;i<=n;++i)
            if(b[i].first.second>a[t].second)a[++t]=b[i].first,bs[t].push_back(b[i].second);
            else if(b[i].first.first==a[t].first && b[i].first.second==a[t].second)bs[t].push_back(b[i].second);
        n=t,t=0;
        for(register int i=1;i<=n;++i)
            xp[i]=1.0/(db)a[i].first,yp[i]=1.0/(db)a[i].second;
        for(register int i=1;i<=n;++i){
            while(tp>1 && (yp[i]-yp[stk[tp]])/(xp[i]-xp[stk[tp]])<xl[tp])--tp;
            stk[++tp]=i,xl[tp]=(yp[i]-yp[stk[tp-1]])/(xp[i]-xp[stk[tp-1]]);
        }
        /*for(register int i=1;i<=n;++i){
            db minx=lar,maxx=0;
            const db xn=xp[i],yn=yp[i];
            for(register int j=1;j<i;++j)
                maxx=_max(maxx,(xn-xp[j])/(yp[j]-yn));
            for(register int j=i+1;j<=n;++j)
                minx=_min(minx,(xn-xp[j])/(yp[j]-yn));
            //printf("%.15lf %.15lf %d %d
    ",maxx,minx,a[i].first,a[i].second);
            if(minx-maxx>=eps)
                for(auto&j:bs[i])ans[++t]=j;
        }*/
        for(register int i=1;i<=tp;++i)
            for(auto &j:bs[stk[i]])ans[++t]=j;
        sort(ans+1,ans+t+1);
        for(register int i=1;i<=t;++i)printf("%d ",ans[i]);
        puts("");
        return 0;
    }
    View Code

    T2

    • 体验到了板子不会打的绝望。
    • 裸的高斯消元。
    • 不过会高斯消元也得不了多少分因为自己不会得到一个方程的解。
    • 正解直接将目标方程的元消去,最终得到的解就是答案的相反数,因为保证有解所以一定可以消干净。
    • 时间复杂度$Theta(N^3)$,空间复杂度$Theta(N^2)$。
    • 听说不少人觉得读入难,其实吧,只要用一个map映射string就可以了,挺简单的,考试5分钟就打完了。
    #include<cstdio>
    #include<string>
    #include<map>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int const N=203;
    int n,tot;
    double a[N][N],c[N];
    map<string,int>qj;
    bool vis[N];
    inline double _abs(double x){
        return x<0?-x:x;
    }
    inline void _swap(double &x,double &y){
        double z=x;
        x=y,y=z;
        return ;
    }
    inline void Gauss(){
        for(register int i=1,now=1;i<n;now=++i){
            for(register int j=i+1;j<n;++j)
                if(_abs(a[j][i])>_abs(a[now][i]))now=j;
            if(!_abs(a[now][i]))continue;
            double x=a[now][i];
            for(register int j=1;j<=n;++j)
                _swap(a[i][j],a[now][j]),a[i][j]/=x;
            for(register int j=1;j<=n;++j){
                if(j==i)continue;
                x=a[j][i];
                for(register int k=i;k<=n;++k)
                    a[j][k]-=a[i][k]*x;
            }
        }
        return ;
    }
    int main(){
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        scanf("%d",&n);
        string s;
        char ss[5];double zz;
        int xs=1;
        for(register int i=1;i<=n;++i,xs=1)
            while(1){
                scanf("%lf",&zz);zz*=xs;
                cin>>s;
                if(qj[s])a[i][qj[s]]=zz;
                else a[i][qj[s]=++tot]=zz;
                scanf("%s",ss);
                if(ss[0]=='=')xs=-1;
                else if(ss[0]=='H'){
                    scanf("%lf",&c[i]);
                    break;
                }
            }
        n=(tot>n?tot:n)+1;
        for(register int i=1;i<n;++i)a[i][n]=c[i];
        while(1){
            scanf("%lf",&zz),zz*=xs;
            cin>>s;
            if(qj[s])a[n][qj[s]]=zz;
            else a[n][qj[s]=++tot]=zz;
            scanf("%s",ss);
            if(ss[0]=='=')xs=-1;
            else if(ss[0]=='H')break;
        }
        n=max(n,tot+1);
        Gauss();
        a[n][n]?printf("%.1lf",-a[n][n]):puts("0.0");
        return 0;
    }
    View Code

    T3

    • dfs+信仰-1成功30。
    • 首先时间显然随k的增加单调不降,所以可以二分答案。
    • 因为选出的k个人的位置在t时刻后的相对位置不能发生改变,所以题意可以转化成最长上升子序列。
    • 求出时间后,我们考虑如何构造字典序最小的最优解。
    • LIS可以看成一棵树,每次转移相当于新加一个叶节点。
    • 对于两个深度都为k的节点x,y,设lca(x,y)=fa。
    • 那么如果x到fa路径上的最小编号小于y到fa路径上的最小编号,那么深度为k的解x比y优。
    • 于是我们可以求出任意深度的最优解,但这个最优解的转移位置任意,而LIS的解必须保证权值单调上升。
    • 我们可以对于每个深度开一棵动态开点线段树,维护前缀最优解就可以正确转移了。
    • 由于博主太垃圾不会树状数组所以无论是LIS还是构造字典序最小的解都用的线段树而且不是zkw,所以常数巨大会T。
    • 所以博主用了一个优化lca的常用方法。
    • 可能大家不是很在意倍增lca的log,但事实上直接设一个极值比如log100000的做法常数很大。
    • 优化很简单,预处理出1~n每个数的log值,进行倍增时只倍增到log[dep]。进行这种优化后博主可以通过本题。
    • 时间复杂度$Theta(NlogNlogT+Nlog^2N)$,空间复杂度$Theta(NlogN)$。
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    #define L tr[k].lc
    #define R tr[k].rc
    #define LC Tr[k].ls
    #define RC Tr[k].rs
    using namespace std;
    int const N=1e5+5,M=86400;
    int n,k;
    struct node{
        int a,id;
        ll c;
    }q[N];
    int p[N];
    pair<long double,int>b[N];
    struct Ljj{
        int lc,rc,w;
    }tr[N<<3];
    struct S_Tree{
        int ls,rs,val,f;
    }Tr[N*100];
    int tot,rt[N],Log[N],dep[N],f[N][18],mx[N][18];
    int ans[N];
    inline ll read(){
        ll ss(0),pp(1);char bb(getchar());
        for(;bb<48||bb>57;bb=getchar())if(bb=='-')pp=-1;
        while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
        return ss*pp;
    }
    inline void _swap(int &x,int &y){
        int z=x;
        x=y,y=z;
        return ;
    }
    inline int min(int x,int y){
        return x<y?x:y;
    }
    inline int max(int x,int y){
        return x>y?x:y;
    }
    void build(int x,int y,int k){
        L=x,R=y;
        if(x==y)return ;
        int mid=x+y>>1;
        return build(x,mid,k<<1),build(mid+1,y,k<<1|1);
    }
    void clear(int k){
        if(!L||!tr[k].w)return ;
        tr[k].w=0;
        return clear(k<<1),clear(k<<1|1);
    }
    int ask(int x,int y,int k){
        if(L>=x&&R<=y)return tr[k].w;
        int mid=L+R>>1,as=0;
        if(x<=mid)as=ask(x,y,k<<1);
        if(y>mid)as=max(as,ask(x,y,k<<1|1));
        return as;
    }
    void add(int x,int y,int k){
        if(L==R){tr[k].w=max(tr[k].w,y);return ;}
        int mid=L+R>>1;
        if(x<=mid)add(x,y,k<<1);
        else add(x,y,k<<1|1);
        tr[k].w=max(tr[k<<1].w,tr[k<<1|1].w);
        return ;
    }
    inline bool check(int x){
        clear(1);
        for(register int i=1;i<=n;++i)b[i].first=0.5*x*x*q[i].a+q[i].c,b[i].second=i;
        sort(b+1,b+n+1);
        int now=0;
        b[0].first=b[1].first+1;
        for(register int i=1;i<=n;++i)
            p[b[i].second]=now=now+(b[i].first!=b[i-1].first);
        for(register int i=1,z;i<=n;++i){
            z=0;
            if(p[i]!=1)z=ask(1,p[i]-1,1);
            add(p[i],++z,1);
            if(z>=k)return 1;
        }
        return 0;
    }
    inline int getmin(int x,int y){
        if(!x||!y)return x+y;
        if(x==y)return x;
        int xm=x,ym=y,xx=x,yy=y;
        for(register int i=Log[dep[x]];~i;--i)
            if(f[x][i]^f[y][i]){
                xm=min(xm,mx[x][i]),ym=min(ym,mx[y][i]);
                x=f[x][i],y=f[y][i];
            }
        return xm<ym?xx:yy;
    }
    inline void down(int k){
        if(!LC)LC=++tot;
        if(!RC)RC=++tot;
        int x=Tr[k].f;
        Tr[k].f=0;
        Tr[LC].val=getmin(Tr[LC].val,x),Tr[LC].f=getmin(Tr[LC].f,x);
        Tr[RC].val=getmin(Tr[RC].val,x),Tr[RC].f=getmin(Tr[RC].f,x);
        return ;
    }
    int Query(int l,int r,int x,int k){
        if(!k)return 0;
        if(r<=x)return Tr[k].val;
        if(Tr[k].f&&l^r)down(k);
        int mid=l+r>>1,zz=Query(l,mid,x,LC);
        if(x>mid)zz=getmin(zz,Query(mid+1,r,x,RC));
        return zz;
    }
    void Insert(int l,int r,int x,int y,int &k){
        if(!k)k=++tot;
        if(l>=x){
            Tr[k].val=getmin(y,Tr[k].val),Tr[k].f=getmin(y,Tr[k].f);
            return ;
        }
        if(Tr[k].f&&l^r)down(k);
        int mid=l+r>>1;
        if(x<=mid)Insert(l,mid,x,y,LC);
        Insert(mid+1,r,x,y,RC);
        Tr[k].val=getmin(Tr[LC].val,Tr[RC].val);
        return ;
    }
    int main(){
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        n=read(),k=read();
        Log[0]=-1;
        for(register int i=1;i<=n;++i)q[i].c=read(),q[i].a=read(),q[i].id=i,Log[i]=Log[i>>1]+1;
        sort(q+1,q+n+1,[](node skyh,node yxs){
            return skyh.c<yxs.c;
        });
        build(1,n,1);
        int l=0,r=M;
        while(l<r){
            int mid=l+r+1>>1;
            if(check(mid))l=mid;
            else r=mid-1;
        }
        printf("%d
    ",l);
        ++k;
        if(check(l))return puts("-1"),0;
        clear(1),memset(mx,0x3f,sizeof(mx));
        for(register int i=1;i<=n;++i)b[i].first=0.5*l*l*q[i].a+q[i].c,b[i].second=i;
        sort(b+1,b+n+1);
        int now=0;
        b[0].first=b[1].first+1;
        for(register int i=1;i<=n;++i)
            p[b[i].second]=now=now+(b[i].first!=b[i-1].first);
        for(register int i=1,z,x,y;i<=n;++i){
            z=0,y=q[i].id;
            if(p[i]!=1)z=ask(1,p[i]-1,1);
            add(p[i],z+1,1);
            if(p[i]!=1)f[y][0]=Query(1,n,p[i]-1,rt[z]);
            mx[y][0]=min(y,f[y][0]),dep[y]=z+1;
            for(register int j=0;j<Log[z];++j)
                f[y][j+1]=f[f[y][j]][j],mx[y][j+1]=min(mx[y][j],mx[f[y][j]][j]);
            Insert(1,n,p[i],y,rt[z+1]);
        }
        now=Query(1,n,n,rt[k-1]);
        for(register int i=1;i<k;++i)
            ans[i]=now,now=f[now][0];
        sort(ans+1,ans+k);
        for(register int i=1;i<k;++i)
            printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Android 判断字符串是否为空
    Android 7.0以上版本 系统解决拍照的问题 exposed beyond app through ClipData.Item.getUri()
    laravel中的登录页面逻辑
    linux的典型分支:
    laravel模型表建立外键约束的使用:
    laravel中的plicy授权方法:
    laravel中的storePublicly对上传的文件设置上传途径
    GitHub下的文件放到Linux系统下
    laravel注册行为的方法和逻辑
    laravel的日志服务
  • 原文地址:https://www.cnblogs.com/remarkable/p/11687010.html
Copyright © 2020-2023  润新知