zoukankan      html  css  js  c++  java
  • Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020

    传送门

    A - Hitachi String

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    char s[15];
    int main() {
        //freopen("in.txt","r",stdin);
        scanf("%s",s);
        int n=strlen(s);
        if(n&1) printf("No
    ");
        else {
            bool f=true;
            for(int i=0;i<n;i+=2) {
                if(s[i]!='h'||s[i+1]!='i') f=false;
            }
            printf("%s
    ",f?"Yes":"No");
        }
        return 0;
    }
    A.cpp

    B - Nice Shopping

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    int a[N],b[N];
    int main() {
        //freopen("in.txt","r",stdin);
        int n,m,q,mi=1e9,ans=1e9;
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            mi=min(mi,a[i]);
        }
        for(int i=1;i<=m;i++) {
            scanf("%d",&b[i]);
            ans=min(ans,mi+b[i]);
        }
        for(int i=0,x,y,c;i<q;i++) {
            scanf("%d%d%d",&x,&y,&c);
            ans=min(ans,a[x]+b[y]-c);
        }
        printf("%d
    ",ans);
        return 0;
    }
    B.cpp

    C - ThREE

    题意:给一个有N个节点的无根树,要求将1~N分别给N个结点当作权值,且满足任意一对距离为3的节点权值的和或积是3的倍数,若不存在输出-1。

    数据范围:$2 leq N leq 2 imes 10^{5}$

    题解:可以发现只有两个模3为1的数和两个模3为2的数的情况,不满足和或积是3的倍数。以1为根,求出每个点的深度,距离为3的两个节点深度差为3或1,因此可以根据深度奇偶性来分配模为1和模为2的数。

    这里记深度为奇数的个数为x,深度为偶数的个数为y。

    1.$xgeq frac{N}{3} and ygeq frac{N}{3}$

    将模为1的数依次分配给深度为奇数的点,将模为2的数依次分配给偶数深度的点,剩余的数随便分配。

    2.$x leq frac{N}{3}$

    将模为0的数以此分配给深度为奇数的点,其它数分配给深度为偶数的点。

    3.$y leq frac{N}{3}$

    将模为0的数以此分配给深度为偶数的点,其它数分配给深度为奇数的点。

    以上包含所有情况,因此不存在的情况没有。

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=2e5+5;
    vector<int> G[N];
    int dep[N],ans[N];
    void dfs(int u,int fa) {
        for(auto v:G[u]) {
            if(v==fa) continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
        }
    }
    int main() {
        //freopen("in.txt","r",stdin);
        int n;
        scanf("%d",&n);
        for(int i=1,u,v;i<n;i++) {
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,-1);
        vector<int> A,B,V[3],Ans[2];
        for(int i=1;i<=n;i++) {
            if(dep[i]&1) A.push_back(i);
            else B.push_back(i);
        }
        for(int i=1;i<=n;i++) {
            V[i%3].push_back(i);
        }
        if(A.size()>=V[1].size()&&B.size()>=V[2].size()) {
            for(auto it:V[1]) Ans[0].push_back(it);
            for(auto it:V[2]) Ans[1].push_back(it);
            int t=A.size()-V[1].size();
            for(int i=0;i<t;i++) Ans[0].push_back(V[0][i]);
            for(int i=t;i<V[0].size();i++) Ans[1].push_back(V[0][i]);
        }
        else if(A.size()<V[1].size()) {
            for(int i=0;i<A.size();i++) Ans[0].push_back(V[0][i]);
            for(int i=A.size();i<V[0].size();i++) Ans[1].push_back(V[0][i]);
            for(auto it:V[1]) Ans[1].push_back(it);
            for(auto it:V[2]) Ans[1].push_back(it);
        }
        else {
            for(int i=0;i<B.size();i++) Ans[1].push_back(V[0][i]);
            for(int i=B.size();i<V[0].size();i++) Ans[0].push_back(V[0][i]);
            for(auto it:V[1]) Ans[0].push_back(it);
            for(auto it:V[2]) Ans[0].push_back(it);
        }
        for(int i=0;i<A.size();i++) {
            ans[A[i]]=Ans[0][i];
        }
        for(int i=0;i<B.size();i++) {
            ans[B[i]]=Ans[1][i];
        }
        for(int i=1;i<=n;i++) {
            printf("%d%c",ans[i],i==n?'
    ':' ');
        }
        return 0;
    }
    C.cpp

     D - Manga Market

    题意:有N个商店,当到达第i个商店的时间为t,则在该商店排队ai*t+bi时间单位,问T个时间单位最多能到多少个商店买东西(一个商店只能买一次)。

    数据范围:$1 leq N leq 2 imes 10^{5},0 leq ai,bi,T leq 10^{9}$

    题解:考虑当前时刻去哪个商店更优,设t时刻准备去第i个商店比第j个商店更优,可以得出:

    $1+a_{i} imes(t+1)+b_{i}+1+a_{j} imes(t+1+a_{i} imes(t+1)+b_{i}+1)+b_{j} leq1+a_{j} imes(t+1)+b_{j}+1+a_{i} imes(t+1+a_{j} imes(t+1)+b_{j}+1)+b_{i}Leftrightarrow frac{a_{j}}{b_{j}+1} geq frac{a_{i}}{b_{i}+1}$

    将N个商店按$frac{a}{b+1}$降序,然后进行动态规划,按最暴力的需要O(N^2)。

    1.当a=0时,显然按b从小到大取。

    2.当a!=0时,可以发现时间是指数级上升的,显然能去的商店不超过30个。

    定义f[i][j]代表1~i个商店里去了j个商店后的最少时间,然后二分判断把a=0的商店加进去,更新答案即可。

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=2e5+5;
    struct P {
        int a,b;
        bool operator <(const P &t) const {
            return a*(t.b+1)>t.a*(b+1);
        }
    }p[N];
    ll pre[N];
    int n,t,cnt=0,tot=0;
    int cal() {
        ll f[35];
        for(int i=0;i<35;i++) f[i]=(i?1e9:0);
        for(int i=0;i<cnt;i++) {
            for(int j=30;j>=0;j--) {
                if(f[j]==1e9) continue;
                f[j+1]=min(f[j+1],(f[j]+1)*(p[i].a+1)+p[i].b);
                if(f[j+1]>t) f[j+1]=1e9;
            }
        }
        int ans=0;
        for(int i=0;i<32;i++) {
            if(f[i]!=1e9) {
                int x=t-f[i];
                int l=1,r=tot,y=-1;
                while(l<=r) {
                    int mid=(l+r)>>1;
                    if(pre[mid]<=x) y=mid,l=mid+1;
                    else r=mid-1;
                }
                if(y!=-1) ans=max(ans,i+y);
                else ans=max(ans,i);
            }
        }
        return ans;
    }
    int main() {
        //freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&t);
        for(int i=0,a,b;i<n;i++) {
            scanf("%d%d",&a,&b);
            if(a==0) pre[++tot]=b;
            else p[cnt++]={a,b};
        }
        sort(p,p+cnt),sort(pre+1,pre+tot+1);
        for(int i=1;i<=tot;i++) pre[i]+=pre[i-1]+1;
        printf("%d
    ",cal());
        return 0;
    }
    D.cpp
  • 相关阅读:
    Redis的基本操作
    Redis下载和安装-windows
    Redis介绍
    day08 网络编程
    day07
    day06
    python day05
    Day04
    windows自带反编译chm文件
    CSS Hack表 各版本IE、chrome、firefox、opera
  • 原文地址:https://www.cnblogs.com/zdragon1104/p/12448715.html
Copyright © 2011-2022 走看看