• 牛客网 长安大学第三届ACM-ICPC程序设计竞赛(同步赛)部分题解


    A题

    暴力计算时间即可.

    #include <bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> p;
    p operator +(const p &_,const p &__){
        p ret;
        ret.second=(_.second+__.second);
        ret.first=(_.first+__.first+ret.second/60)%24;
        ret.second%=60;
        return ret;
    }
    int main(){
        int t; scanf("%d",&t);
        while (t--){
            p t=p(12,0);
            int x;
            scanf("%d",&x);
            t=t+p(0,x);
            if (t.second>=10)
            printf("%d:%d
    ",t.first,t.second);
            else 
            printf("%d:0%d
    ",t.first,t.second);
        }
    }
    View Code

    B题

    计算概率分类讨论.

    首先路程大于等于2圈肯定不行

    一圈以内及一圈概率计算一波

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
        int t; scanf("%d",&t);
        while (t--){
            int k,x; scanf("%d%d",&k,&x);
            if (k>=2*x) puts("0.00");
            else if (k<x){
                double in=1.*k/x,out=1-in;
                printf("%.2lf
    ",in*in/2+in*out+out*in+out*out);
            }
            else{
                double in=1.*(k-x)/x,out=1-in;
                printf("%.2lf
    ",out*out/2);
            }
        }
    }
    View Code

    C题

    二分答案,O(n)验证,小心边界问题

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    int n,a[N],num,b[N];
    long long k;
    long long check(int x){
    //    cerr<<"x"<<x<<endl;
        int j=n; long long tot=0;
        num=0;
        for (int i=n; i>=1; --i){
            if (a[i]>x) ++num;
            while (num>1&&j>i) num-=(a[j]>x),--j;
            tot+=j-i;
    //        cerr<<"i j"<<i<<" "<<j<<" "<<num<<endl;
        }
    //    cerr<<tot<<endl;
        return tot;
    }
    int main(){
        int t;
        scanf("%d",&t);
        while (t--){
            scanf("%d%lld",&n,&k);
            int ans=2333;
            for (int i=1; i<=n; ++i) scanf("%d",&a[i]),b[i]=a[i];
            sort(b+1,b+n+1);
            for (int l=1,r=n,mid=(l+r)>>1; l<=r; mid=(l+r)>>1)
            if (1ll*n*(n-1)/2-check(b[mid])<k) ans=mid,r=mid-1; else l=mid+1;
            printf("%d
    ",b[ans]); 
        }
    }
    View Code

    D题

    莫队算法(有信仰就能过)

    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> p;
    const int N=100010;
    pair<p,int> a[N];
    int n,m,s,q,an[N],num[N],fa[N],d[N];
    int find(int x){
        return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    bool cmp(const pair<p,int> &_, const pair<p,int> &__){
        return d[_.first.first]<d[__.first.first]||(d[_.first.first]==d[__.first.first]&&_.first.second<__.first.second);
    }
    int main(){
        int t; scanf("%d",&t);
        for (int i=1; i<=100000; ++i) d[i]=i/1000;
        while (t--){
            scanf("%d%d",&n,&m);
            for (int i=1; i<=n; ++i) fa[i]=i;
            for (int i=1; i<=m; ++i){
                int x,y; scanf("%d%d",&x,&y);
                x=find(x); y=find(y);
                if (x==y) continue;
                fa[x]=y;
            }
            scanf("%d",&q);
            for (int i=1; i<=q; ++i) scanf("%d%d",&a[i].first.first,&a[i].first.second),a[i].second=i;
            for (int i=1; i<=n; ++i) num[i]=0;
            for (int i=1; i<=n; ++i) find(i);
            sort(a+1,a+q+1,cmp);
            int l=1,r=0,ans=0;
            for (int i=1; i<=q; ++i){
                int ll=a[i].first.first,rr=a[i].first.second;
                while (r<rr){
                    ++r;
                    if (!num[fa[r]]++) ++ans;
                }
                while (r>rr){
                    if (!--num[fa[r]]) --ans;
                    --r;
                }
                while (l>ll){
                    --l;
                    if (!num[fa[l]]++) ++ans;
                }
                while (l<ll){
                    if (!--num[fa[l]]) --ans;
                    ++l;
                }
                an[a[i].second]=ans;
            }
            for (int i=1; i<=q; ++i) printf("%d
    ",an[i]);
        }
    }
    View Code

    E题

    OEIS大法好(待研究)

    #include<bits/stdc++.h>
    using namespace std;
    int f[100];
    int main(){
        int t; scanf("%d",&t);
        f[1]=7; for (int i=2; i<=11; ++i) f[i]=f[i-1]*7/*,printf("%d
    ",f[i])*/;
        while (t--){
            int x; scanf("%d",&x);
            printf("%.0Lf
    ",2*ceil((long double)sqrt(12ll*x-3)));
        }
    }
    View Code

    F题

    貌似是一道codeforces原题,大佬讲过,未AC

    G题

    求树上某点出发最长链,再分类讨论.

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1000010;
    int ne[N<<1],fi[N],b[N<<1],k,dep[N],dis[N],n,q;
    void add(int x,int y){
        ne[++k]=fi[x]; b[fi[x]=k]=y;
    }
    void dfs(int x,int fa,int deep){
        dep[x]=deep;
        dis[x]=max(dis[x],deep);
        for (int j=fi[x]; j; j=ne[j])
        if (b[j]!=fa) dfs(b[j],x,deep+1);
    }
    int main(){
        int t; scanf("%d",&t);
        while (t--){
            scanf("%d",&n);
            for (int i=1; i<=n; ++i) fi[i]=dep[i]=dis[i]=0; k=0;
            for (int i=1; i<n; ++i){
                int x,y; scanf("%d%d",&x,&y);
                add(x,y); add(y,x);
            }
            dfs(1,0,0);
            int mx=1;
            for (int i=2; i<=n; ++i)
            if (dep[i]>dep[mx]) mx=i;
            dep[mx]=0;
            dfs(mx,0,0);
            int mxx=1;
            for (int i=2; i<=n; ++i)
            if (dep[i]>dep[mxx]) mxx=i;
            dep[mxx]=0;
            dfs(mxx,0,0);
            scanf("%d",&q);
            for (int i=1; i<=q; ++i){
                int x,y; scanf("%d%d",&x,&y);
    //            cerr<<y-(n-dis[x]-1)*2<<" "<<dis[x]<<endl;
                if (dis[x]>=y){
                    printf("%d
    ",y+1);
    //                cerr<<"dis"<<dis[x]<<" "<<y<<endl;
                }
                else if (y<=(n-dis[x]-1)*2){
                    printf("%d
    ",max(y/2+1,dis[x]+1));
    //                cerr<<"2t"<<endl;
                }
                else printf("%d
    ",max(dis[x]+1,(n-dis[x]-1)+1+y-(n-dis[x]-1)*2));
            }
        }
    }
    View Code

    H题

    两次01背包

    #include <bits/stdc++.h>
    using namespace std;
    const int INF=1e9+7;
    const int N=1010;
    int n,m,q;
    int a[N],b[N],c[N],d[N],f[N],g[N+N];
    int main(){
        int t; scanf("%d",&t);
        while (t--){
            scanf("%d",&n);
            int suma=0;
            for (int i=1; i<=n; ++i) scanf("%d%d",&a[i],&b[i]),suma+=a[i];
            scanf("%d",&m);
            for (int i=1; i<=m; ++i) scanf("%d%d",&c[i],&d[i]);
            scanf("%d",&q);
            for (int i=1; i<=1000; ++i) f[i]=INF;
            for (int i=1; i<=n; ++i)
            for (int j=1000; j>=b[i]; --j)
            f[j]=min(f[j-b[i]]+a[i],f[j]);
            for (int i=1; i<=2000; ++i) g[i]=0;
            for (int i=1; i<=m; ++i)
            for (int j=2000; j>=d[i]; --j)
            g[j]=max(g[j-d[i]]+c[i],g[j]);
            int ans=0;
            for (int i=0; i<=1000; ++i)
            ans=max(ans,suma-f[i]+g[i+q]);
            printf("%d
    ",ans);
        }
    }
    View Code

    I题

    毫无想法

    看起来是压轴题.(待研究)

    J题

    贪心的代码不懂

    不过可以用带权最小路径覆盖做.

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    typedef pair<long long,long long> p;//?
    const long double INF=1e11;
    const int N=210;
    struct edge{
        int y,cap;
        long double cost;
        int op;
        edge(int y,int cap,long double cost,int op):y(y),cap(cap),cost(cost),op(op){}
    };
    vector<edge> g[N<<1];
    p prep[N<<1];
    bool in[N<<1];
    int a[N],b[N];
    long double f[N<<1];
    int n,m,s,t;
    long double spfa(){
        queue<int> q;
        fill(f+s,f+t+1,INF);
        fill(in+s,in+t+1,0);
        f[s]=0; q.push(s); in[s]=1;
        while (!q.empty()){
            int x=q.front(); q.pop(); in[x]=0;
            for (size_t j=0; j<g[x].size(); ++j){
                edge e=g[x][j];
                if (e.cap&&f[e.y]>f[x]+e.cost){
                    f[e.y]=f[x]+e.cost;
                    prep[e.y]=p(x,j);
                    if (!in[e.y]) q.push(e.y),in[e.y]=1;
                } 
            }
        }
        if (f[t]>=0) return -1;
        int that=INF;
        for (int i=t; i!=s; i=prep[i].first) that=min(that,g[prep[i].first][prep[i].second].cap);
        for (int i=t; i!=s; i=prep[i].first){
            edge &e=g[prep[i].first][prep[i].second];
            e.cap-=that;
            g[e.y][e.op].cap+=that;
        }
        return that*f[t];
    }
    bool init(int x,bool a,int y,bool b){
        if (a==b) return x>=y;
        if (a) return x>=(y<<1);
        return ((x*x)<<1)>=y*y;
    }
    void add(int x,int y,int cap,long double cost){
        g[x].push_back(edge(y,cap,cost,g[y].size()));
        g[y].push_back(edge(x,0,-cost,g[x].size()-1));
    }
    void myunique(int *r,int &len){
        sort(r+1,r+len+1);
        len=unique(r+1,r+len+1)-r-1;
    }
    signed main(){
        int ttt; scanf("%lld",&ttt);
        while (ttt--){
            scanf("%lld%lld",&n,&m);
            for (int i=1; i<=n; ++i) scanf("%lld",&a[i]);
            for (int i=1; i<=m; ++i) scanf("%lld",&b[i]);
            myunique(a,n); myunique(b,m);
            s=0; t=((n+m)<<1)+1;
            for (int i=s; i<=t; ++i) g[i].clear();
            for (int i=1; i<=n; ++i) add(s,i,1,a[i]*a[i]);
            for (int i=1; i<=m; ++i) add(s,n+i,1,acos(-1)*b[i]*b[i]);
            for (int i=1; i<=n+m; ++i) add(i,n+m+i,1,-INF),add(n+m+i,t,1,0);
            for (int i=1; i<=n+m; ++i)
            for (int j=1; j<=n+m; ++j)
            if (i!=j&&init(i<=n?a[i]:b[i-n],i<=n,j<=n?a[j]:b[j-n],j<=n)) add(n+m+i,j,1,0);
            long double t,ans=0; while ((t=spfa())!=-1) ans+=t;
            printf("%.2Lf
    ",ans+(n+m)*INF);
        }
    }
    View Code

    K题

    仅有个位数的人过.不过我把另一个AC的叉掉了,我的复杂度为O(q*sqrt(n)*log(n))

    此题数据范围有毒. a[i]<=n 不存在的.(p.s.此题暴力可以水过)

    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #include <bits/stdc++.h>
    using namespace std;
    const int N=20010,NODE=2000010;
    vector<int> g[N];
    struct node{int v,l,r;}T[NODE];
    int ll,rr,sz,root[N],fi[N],ne[N<<1],b[N<<1],top[N],v[N],k,a[N],s,n,q,d;
    map<int,int> mp;
    void clear(){
        for (int i=1; i<=n; ++i) fi[i]=0;
        for (int i=1; i<=n; ++i) g[i].clear();
        mp.clear();
        k=sz=d=0;
    }
    void add(int x,int y){
        ne[++k]=fi[x]; b[fi[x]=k]=y;
    }
    void read(int &x){
        char ch=getchar(); x=0;
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    }
    void init(){
        read(n); s=(int(sqrt(n))>>1)+1;
        for (int i=1; i<n; ++i){
            int x,y; read(x); read(y);
            add(x,y); add(y,x);
        }
        for (int i=1; i<=n; ++i) read(a[i]),mp[a[i]]=1;
        for (map<int,int>::iterator i=mp.begin(); i!=mp.end(); ++i) i->second=++d;
        for (int i=1; i<=n; ++i) g[a[i]=mp[a[i]]].push_back(i);
    }
    int ask(int ind,int l,int r){
        if (!ind) return 0;
        if (ll<=l&&r<=rr) return T[ind].v;
        int mid=(l+r)>>1,ret=0;
        if (ll<=mid) ret+=ask(T[ind].l,l,mid);
        if (mid<rr) ret+=ask(T[ind].r,mid+1,r);
        return ret;
    }
    void fork(int &ind,int pa,int l,int r){
        T[ind=++sz]=T[pa];
        if (l==r) return void(++T[ind].v);
        int mid=(l+r)>>1;
        ll<=mid?fork(T[ind].l,T[pa].l,l,mid):fork(T[ind].r,T[pa].r,mid+1,r);
        T[ind].v=T[T[ind].l].v+T[T[ind].r].v;
    }
    void add(int &ind,int l,int r){
        if (!ind) T[ind=++sz]=T[0];
        if (l==r) return void(T[ind].v+=rr);
        int mid=(l+r)>>1;
        ll<=mid?add(T[ind].l,l,mid):add(T[ind].r,mid+1,r);
        T[ind].v=T[T[ind].l].v+T[T[ind].r].v;
    }
    void build(int x,int fa){
        ll=a[x];
        fork(root[x],root[fa],1,d);
        for (int j=fi[x]; j; j=ne[j])
        if (b[j]!=fa) build(b[j],x);
    }
    void dfs(int x,int fa){
        v[x]=(a[x]==rr);
        for (int j=fi[x]; j; j=ne[j])
        if (b[j]!=fa){
            dfs(b[j],x);
            v[x]+=v[b[j]];
        }
    }
    void zig(int x){
        top[x]=0;
        rr=x; dfs(1,0);
        for (int i=1; i<=n; ++i){
            ll=a[i]; rr=v[i];
            if (rr) add(top[x],1,d);
        }
    }
    void solve(){
        build(1,0);
        for (int i=1; i<=d; ++i) if (g[i].size()>s) zig(i);
        read(q);
        while (q--){
            int x,k,y;
            read(x); read(k); y=x;
            if (mp.find(x)==mp.end()){putchar('0'); putchar('
    '); continue;} 
            x=mp[x]; ll=max(mp.lower_bound(y-k)->second,1); rr=min((--mp.upper_bound(y+k))->second,d);
            if (g[x].size()<=s){
                int ans=0;
                for (size_t j=0; j<g[x].size(); ++j) ans+=ask(root[g[x][j]],1,d);
                printf("%d
    ",ans-g[x].size());
            }
            else printf("%d
    ",ask(top[x],1,d)-g[x].size());
        }
    }
    int main(){
        int t; read(t);
        while (t--){
            init();
            solve();
            clear();
        }
    }
    View Code

    L题

    我wa了好几发.负进制搞一搞.

    #include<bits/stdc++.h>
    using namespace std;
    int st[100];
    int calc(int x){
        memset(st,0,sizeof(st));
        int top=0;
        for (int i=1; i<=4; ++i){
            st[++top]=x%9;
            x/=9;
            if (st[top]>=5){
                st[top]=st[top]-9;
                ++x;
            }
        }
        int ans=0;
        for (int i=1; i<=4; ++i) ans+=abs(st[i]);
        return ans+x;
    }
    int main(){
        int t;
        scanf("%d",&t);
        while (t--){
            int x; scanf("%d",&x);
            int t=1;
            int z=1e9+7;
            printf("%d
    ",calc(x));
        }
    }
    View Code
  • 相关阅读:
    【微积分】 02
    【微积分】 01
    【线性代数】 09
    云南国庆八日游策划书
    Kubectl工具常用命令
    Linux 常用命令缩写及对应的
    kubectl工具的windows安装方法
    Intellij IDEA工具的常用快捷键
    如何理解docker镜像build中的上下文
    【转】在服务器上排除问题的头五分钟&常用命令
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/8849787.html
Copyright © 2020-2023  润新知