zoukankan      html  css  js  c++  java
  • CSP-S 模拟75

      不是一道题不会,是一道题都不会,全是暴力,T1高考数学,T2高斯消元早忘了,高考化学没学好,T3高考物理没学好

      

      

      导弹袭击 

        式子,设其他导弹的速度为(x,y),有用的导弹(a,b)必须满足 存在$frac{A}{a}+frac{B}{b}<=min(frac{A}{x}+frac{B}{y}) $

        直接照着式子打n^2做法,可以拿55~65分

        我们将$a=frac{1}{a},b=frac{1}{b},x=frac{1}{x},y=frac{1}{y}$,那么我们就是求 $Z=Aa+Bb$最小

        转换成函数形式$y=-frac{A}{B}x+frac{Z}{B}$ ,因为A,B为正实数,所以问题转化为求出是否存在一个斜率使得函数过$(a,b)$点的时候纵截距最小

        所以把$(x,y)$转换成二维坐标系上的点$(frac{1}{x},frac{1}{y})$,跑一个下凸包就可以了

        注意细节:跑凸包前先把所有不可能的点咕咕掉!  

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,st[310000],to[310000];
    struct node{
        long double a,b;
        int id;
        bool operator < (const node x)const{
            return (a>x.a)||(a==x.a&&b>x.b);
        }
    }w[310000];
    long double cal(int x,int y){
        if(w[y].a==w[x].a) return 1;
        if(w[y].b==w[x].b) return 1;
        return w[x].a/w[x].b*w[y].a/w[y].b*(w[x].b-w[y].b)/(w[x].a-w[y].a);
    }
    int main(){
        //freopen("slay4.in","r",stdin);
        scanf("%d",&n);
        for(register int i=1;i<=n;i++) scanf("%LF%LF",&w[i].a,&w[i].b),w[i].id=i;
        sort(w+1,w+n+1);
        int num=0;
        for(register int i=1;i<=n;i++){
            if(w[i].a==w[i-1].a&&w[i].b==w[i-1].b){
                to[w[i-1].id]=w[i].id;
            }
            else{
                w[++num].a=w[i].a,w[num].b=w[i].b;
                w[num].id=w[i].id;
            }
        }
        n=num;
        sort(w+1,w+n+1);
        st[++st[0]]=1;
        for(register int i=2;i<=n;i++){
            if(cal(st[st[0]],i)>0) continue;
             while(st[0]>1&&cal(st[st[0]-1],st[st[0]])-cal(st[st[0]],i)>1e-30) st[0]--;
            st[++st[0]]=i;
        }
        num=st[0];
        for(register int i=1;i<=st[0];i++){
            st[i]=w[st[i]].id;
            for(register int j=to[st[i]];j;j=to[j])
                st[++num]=j;
        }
        st[0]=num;
        sort(st+1,st+st[0]+1);
        for(register int i=1;i<=st[0];i++) printf("%d ",st[i]);
    }
    View Code

      炼金术士的疑惑

        高斯消元

        读入很麻烦,但是其它挺简单的,主要是考察了对于高斯消元的理解

        将n个方程读入,第n+1个的询问读入,然后跑一遍高斯消元,高斯消元的过程就是将方程代入其他方程的过程,所以将n个方程消元的过程中代入询问方程并消去询问方程的系数,假设原来询问方程的焓变值为H,消元完之后会变成0,而现在初值是0,那么H就等于最后询问方程的答案的相反数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int n,tot;
    char h[20];
    const long long mod=233333;
    const double eps=1e-6;
    double a[210][210],b[210];
    struct node{
        int ha[233333];
        int insert(){
            int len=strlen(h+1);
            long long sta=0;
            for(register int i=1;i<=len;i++){
                sta=(1ll*sta*33%mod+h[i])%mod;
            }
            if(!ha[sta]) ha[sta]=++tot;
            return ha[sta];
        }
    }H;
    void Gauss(){
        for(register int i=1;i<=n;i++){
            int p=i;
            for(register int j=i+1;j<=n;j++) if(fabs(a[j][i])>fabs(a[p][i])) p=j;
            for(register int j=1;j<=tot+1;j++) swap(a[i][j],a[p][j]);
            if(fabs(a[i][i])<eps) continue; 
            double tmp=a[i][i];
            for(register int j=1;j<=tot+1;j++) a[i][j]/=tmp;
            for(register int j=1;j<=n+1;j++){
                tmp=a[j][i];
                if(i==j) continue;
                for(register int k=1;k<=tot+1;k++){
                    a[j][k]-=a[i][k]*tmp;
                }
            }
        }
    }
    void init(int t){
        double x;
        while(1){
            scanf("%lf%s",&x,h+1);
            int sta=H.insert();
            a[t][sta]=x;
            scanf("%s",h+1);
            if(h[1]=='=') break;        
        }
        while(1){
            scanf("%lf%s",&x,h+1);
            int sta=H.insert();
            a[t][sta]=-x;
            scanf("%s",h+1);
            if(h[1]=='H') break;
        }
        if(t==n+1) return;
        scanf("%lf",&b[t]);    
    }
    int main(){
        scanf("%d",&n);
        for(register int i=1;i<=n;i++) init(i);
        n=max(n,tot);
        tot=n;
        init(n+1);
        for(register int i=1;i<=n+1;i++) a[i][tot+1]=b[i];
        Gauss();
        if(fabs(a[n+1][tot+1])<eps) puts("0.0");
        else printf("%.1lf
    ",-a[n+1][tot+1]);
    }
    View Code

      老司机的狂欢

        主要在于题意转换

        将老司机的初始位置为x,按x从大到小排序,若t秒后老司机不相遇或追及,那么老司机的最终位置还是有序的,即LIS问题,用树状数组维护

        考虑随时间递增,不会相遇的老司机数量会单调递减,可以二分时间,找到k个老司机不相遇的时间t,如果最终二分出的时间算出来有多于k个老司机可以不相遇,那么老司机就要有意见了,输出t后puts("-1")

        如果恰好k个老司机的话,需要求出最小字典序的方案,看求LIS过程,是从前面的某一个位置小于我而序列长度最大的转移到我,类似与一棵树的样子找深度最大的权值小于我的点连边

        如果有两个点满足深度都是最大的,且权值(最终位置)都小于我的,那么求两个点的lca选取点到lca的路径上最小id最小的那个点连边

        因为考虑输出按id排序之后字典序最小,如果最小id最小,那么这条链必定比最小id大的字典序小

        最后找k深度的字典序最小的那条树上从叶子节点到根的链,按id排序后输出即可

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,k,st[110000],fa[110000][20],minn[110000][20],dis[110000];
    struct node{
        long long x,a,pos;
        int id;
        bool operator < (const node b)const{
            return x<b.x;
        }
    }w[110000];
    long long tmp[110000];
    pair<int,int>tr[110000];
    char lca(int x,int y){
        int minnx=x,minny=y;
        int i=0;
        for(;(1<<i)<=dis[y];i++);
        for(register int j=i;j>=0;j--){
            if(fa[y][j]!=fa[x][j]){
                minnx=min(minnx,minn[x][j]);
                minny=min(minny,minn[y][j]);
                x=fa[x][j];
                y=fa[y][j];
            }
        }
        return minnx<minny;
    }
    pair<int,int>askmax(pair<int,int>a,pair<int,int>b){
        if(a.first<b.first) return b;
        else if(a.first>b.first) return a;
        if(lca(a.second,b.second)) return a;
        return b;
    }
    int lowbit(int x){return x&(-x);}
    void add(int x,pair<int,int>w){
        while(x<=n+1){
            tr[x]=max(tr[x],w);
            x+=lowbit(x);
        }
    }
    pair<int,int> ask(int x){
        pair<int,int>ans=make_pair(0,0);
        while(x){
            ans=max(ans,tr[x]);
            x-=lowbit(x);
        }
        return ans;
    }
    int judge(long long mid){
        tmp[0]=0;
        for(register int i=1;i<=n;i++){
            w[i].pos=w[i].x+w[i].a*mid*mid/2;
            tmp[++tmp[0]]=w[i].pos;
        }
        sort(tmp+1,tmp+tmp[0]+1);
        tmp[0]=unique(tmp+1,tmp+tmp[0]+1)-tmp-1;
        for(register int i=1;i<=n;i++)
            w[i].pos=lower_bound(tmp+1,tmp+tmp[0]+1,w[i].pos)-tmp;
        for(register int i=1;i<=n+1;i++) tr[i]=make_pair(0,0);
        for(register int i=1;i<=n;i++){
            pair<int,int> cet=ask(w[i].pos);
            cet.first++;cet.second=w[i].id;
            add(w[i].pos+1,cet);    
        }
        pair<int,int>cet=ask(n+1);
        return cet.first;
    }
    void buildadd(int x,pair<int,int>w){
        while(x<=n+1){
            tr[x]=askmax(tr[x],w);
            x+=lowbit(x);
        }
    }
    pair<int,int> buildask(int x){
        pair<int,int>ans=make_pair(0,0);
        while(x){
            ans=askmax(ans,tr[x]);
            x-=lowbit(x);
        }
        return ans;
    }
    void build(){
        for(register int i=1;i<=n+1;i++) tr[i]=make_pair(0,0);
        memset(fa,0,sizeof(fa));
        memset(minn,0x3f,sizeof(minn));
        for(register int i=1;i<=n;i++){
            pair<int,int> cet=buildask(w[i].pos);
            fa[w[i].id][0]=cet.second;
            minn[w[i].id][0]=cet.second;
            dis[w[i].id]=dis[cet.second]+1;
            for(register int j=1;j<=16;j++){
                fa[w[i].id][j]=fa[fa[w[i].id][j-1]][j-1];
                minn[w[i].id][j]=min(minn[w[i].id][j-1],minn[fa[w[i].id][j-1]][j-1]);
            }
            cet.first++;cet.second=w[i].id;
            buildadd(w[i].pos+1,cet);    
        }
    }
    int main(){
        //freopen("driver3.in","r",stdin);
        //freopen("3.out","w",stdout);
        scanf("%d%d",&n,&k);
        for(register int i=1;i<=n;i++) scanf("%lld%lld",&w[i].x,&w[i].a),w[i].id=i;
        sort(w+1,w+n+1);
        int l=0,r=86400,mid,ans;
        while(l<=r){
            mid=(l+r)>>1;
            if(judge(mid)>=k) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d
    ",ans);
        if(judge(ans)>k) puts("-1");
        else{
            build();
            int x=buildask(n+1).second;
            st[++st[0]]=x;
            while(fa[x][0]!=0){
                x=fa[x][0];
                st[++st[0]]=x;
            }
            sort(st+1,st+st[0]+1);
            for(register int i=1;i<=st[0];i++) printf("%d
    ",st[i]);
        }
    }
    View Code
  • 相关阅读:
    [译文] 实体与值对象到底是不是一回事?
    实现 WebApi 自托管服务宿主于 WinForms 及其交互
    [译文] C# 8 已成旧闻, 向前, 抵达 C# 9!
    [译文] 为什么你在 C# 里总是应该使用 "var" 关键字
    通过设置iis在局域网中访问网页
    windows 10 安装使用kafka
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定义命名化和类型化的客户端
    Asp.net Core 2.0 OpenId Connect Handler缺失Claims?
  • 原文地址:https://www.cnblogs.com/heoitys/p/11686681.html
Copyright © 2011-2022 走看看