zoukankan      html  css  js  c++  java
  • Codeforces Round #379 (Div. 2)

    A ~~

    B ~~

    C

    对于第二种方法,我们可以任取一个换c[i]个potions,花费d[i];或者是不取,我的做法就是枚举这些情况,得到剩余的s,再尽量优的获取小的a[i];

    枚举+二分

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e19+1LL;
    const double Pi = acos(-1.0);
    const int N = 5e5+10, maxn = 1e3+20, mod = 1e9+7, inf = 2e9;
    
    LL n,m,k,x,s,d[N],c[N],san[N];
    struct ss{
            LL a,b;
    }p[N],p1[N];
    int check(LL T) {
            LL miT = INF;
            for(int i = 1; i <= k+1; ++i) {
                LL ret = s - d[i];
                if(ret < 0) continue;
                if(ret < san[1]) {
                    miT = min(miT,(n-c[i])*x);
                } else {
                    if(san[m] < ret) {
                        miT = min(miT,(n-c[i])*p1[m].a);
                    }
                    else  {
                        int pos = upper_bound(san+1,san+m+1,ret) - san - 1;
                        miT = min(miT,(n-c[i])*p1[pos].a);
                    }
                }
            }
            if(miT <= T) return 1;
            else return 0;
    }
    bool cmp(ss s1,ss s2) {
            return s1.b < s2.b;
    }
    int main() {
            scanf("%I64d%I64d%I64d%I64d%I64d",&n,&m,&k,&x,&s);
            for(int i = 1; i <= m; ++i) scanf("%I64d",&p[i].a);
            for(int i = 1; i <= m; ++i) scanf("%I64d",&p[i].b);
    
            sort(p+1,p+m+1,cmp);
            int cnt = 0;
            p1[++cnt] = p[1];
            for(int i = 2; i <= m; ++i) {
                if(p[i].a >= p1[cnt].a) continue;
                p1[++cnt] = p[i];
            }
            m = cnt;
            for(int i = 1; i <= m; ++i) san[i] = p1[i].b;
    
            for(int i = 1; i <= k; ++i) scanf("%I64d",&c[i]);
            for(int i = 1; i <= k; ++i) scanf("%I64d",&d[i]);
            LL l = 0, r = x*n;
            LL ans = x * n;
            while(l <= r) {
                LL md = (l+r)>>1;
                if(check(md)) {
                    ans = md, r = md-1;
                } else l = md + 1;
            }
            cout<<ans<<endl;
            return 0;
    }
    C

    D

    想要知道是否有个黑棋能不跳跃棋子一步走到白棋,白棋只有一个,我们将其8个方向第一碰到的黑棋挑出来判断黑棋行走方式是否可以到达白棋就可以了

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e19+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e6+10, maxn = 1e3+20, mod = 1e9+7, inf = 2e9;
    
    int n,x,y,d[N],can;
    char chs[N];
    int ss[8][2] = {-1,0,0,-1,1,0,0,1,1,1,-1,-1,1,-1,-1,1};
    struct ss{int x,y;} c[10],p[N];;
    int go(int j,int i) {
            int ok = 0;
            if(j == 0 && (p[i].x > c[j].x||c[j].x==inf))c[j] = p[i],ok=1;
            if(j == 1 && (p[i].y > c[j].y||c[j].y==inf))c[j] = p[i],ok=1;
            if(j == 2 && (p[i].x < c[j].x||c[j].x==inf))c[j] = p[i],ok=1;
            if(j == 3 && (p[i].y < c[j].y||c[j].y==inf))c[j] = p[i],ok=1;
            if(j == 4 && (p[i].x < c[j].x||c[j].x==inf))c[j] = p[i],ok=1;
            if(j == 5 && (p[i].x > c[j].x||c[j].x==inf))c[j] = p[i],ok=1;
            if(j == 6 && (p[i].x < c[j].x||c[j].x==inf))c[j] = p[i],ok=1;
            if(j == 7 && (p[i].x > c[j].x||c[j].x==inf))c[j] = p[i],ok=1;
            return ok;
    }
    int check(int j,int i) {
            can = 0;
            int xx = ss[j][0] + x;
            int yy = ss[j][1] + y;
            if((p[i].y-y)*(xx-x) != (p[i].x-x)*(yy-y)) return 0;
            if((p[i].y-y)*(yy-y) < 0 || (p[i].x-x)*(xx-x) < 0) return 0;
            if(j > 3 && chs[i] != 'R' ) can = 1;
            else if(j < 4 && chs[i] != 'B' ) can = 1;
            else can = 0;
            return 1;
    }
    int main() {
            char ch[2];
            scanf("%d%d%d",&n,&x,&y);
            for(int i = 1; i <= n; ++i) {
                scanf("%s%d%d",ch,&p[i].x,&p[i].y);
                chs[i] = ch[0];
            }
            for(int i = 0; i < 8; ++i) c[i].x = inf,c[i].y = inf;
            for(int i = 1; i <= n; ++i) {
                for(int j = 0; j < 8; ++j) {
                        if(!check(j,i)||!go(j,i)) continue;
                        if(can) d[j] = 1;
                        else d[j] = 0;
                       // cout<<j<<":"<<can<<endl;
                }
            }
            int ok = 0;
            for(int i = 0; i < 8; ++i) if(d[i]) ok = 1;
            if(ok) puts("YES");else puts("NO");
            return 0;
    }
    D

    E

    首先,对于颜色相同的且相连的点,我们将其看作一个点,那么新图就是黑白相连的树了

    对于一个黑白间隔的图,最少的次数很容易算就是树直径除2,向下取整.

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 200000+10, maxn = 1e3+20, mod = 1e9+7, inf = 2e9;
    
    int n,a[N],fa[N],u[N],v[N],from,ans = -1;
    vector<int >G[N];
    int finds(int x) {return x==fa[x]?x:fa[x]=finds(fa[x]);}
    void dfs(int u,int f,int dep) {
            if(dep > ans) {
                ans = dep;
                from = u;
            }
            for(int i = 0; i < G[u].size(); ++i) {
                int to = G[u][i];
                if(to == f) continue;
                dfs(to,u,dep+1);
            }
    }
    int main() {
            scanf("%d",&n);
            for(int i = 1; i <= n; ++i) scanf("%d",&a[i]);
            for(int i = 1; i < n; ++i) scanf("%d%d",&u[i],&v[i]);
            for(int i = 1; i <= n; ++i) fa[i] = i;
            for(int i = 1; i < n; ++i) {
                int fx = finds(u[i]);
                int fy = finds(v[i]);
                if(a[u[i]] == a[v[i]]) {
                    fa[fx] = fy;
                }
            }
            for(int i = 1; i < n; ++i) {
                int fx = finds(u[i]);
                int fy = finds(v[i]);
                if(a[fx] != a[fy]) {
                    G[fx].push_back(fy);
                    G[fy].push_back(fx);
                }
            }
            dfs(finds(1),-1,1);
            dfs(from,-1,1);
            printf("%d
    ",ans/2);
            return 0;
    }
    E

    F

    观察i,j得到

      (a[i] and a[j]) +   (a[i] or a[j]) = a[i] + a[j];

    我们就这样轻松得到a数组了

    如何判断?

    对于数组a,取出二进制下60每个数的01情况来检查这个a数组是否满足题目条件 O(N*60)

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 200000+10, maxn = 1e3+20, mod = 1e9+7, inf = 2e9;
    LL a[N],n,b[N],c[N],num[N];
    LL sum = 0;
    int main() {
            scanf("%I64d",&n);
            for(int i = 1; i <= n; ++i) scanf("%I64d",&b[i]),sum+=b[i];
            for(int i = 1; i <= n; ++i) scanf("%I64d",&c[i]),sum+=c[i];
            if(sum%(2LL*n)!=0) {
                puts("-1");
                return 0;
            }
            sum = sum/(2*n);
            for(int i = 1; i <= n; ++i)
            {
                LL now = b[i]+c[i] - sum;
                if(now%n!=0) {
                    puts("-1");
                    return 0;
                }
                a[i] = now/n;
            }
            for(int i = 1; i <= n; ++i) {
                LL tmp = a[i];
                for(int j = 1; j <= 60; ++j) {
                    num[j]+=tmp%2;
                    tmp/=2;
                }
            }
            for(int i = 1; i <= n; ++i) {
                LL tmpb = 0, tmpc = 0;
                for(int j = 1; j <= 60; ++j) {
    
                    if((a[i]&(1LL<<j-1))) tmpc += 1LL*n*(1LL<<j-1);
                    else tmpc += 1LL*num[j]*(1LL<<j-1);
    
                    if(a[i]&(1LL<<j-1)) tmpb += 1LL*num[j]*(1LL<<j-1);
                }
                //cout<<tmpb<<" "<<tmpc<<endl;
                if(tmpb != b[i] || tmpc != c[i]) {
                    puts("-1");;
                    return 0;
                }
            }
            for(int i = 1; i <= n; ++i) cout<<a[i]<<" ";
            return 0 ;
    }
    f
  • 相关阅读:
    使用visio 2007对现有的数据库进行反向工程
    GOOGLE地图坐标拾取方法、GOOGLE地图获取坐标方法
    Visio 2007中进行数据库建模时如何显示字段类型以及概念名称
    WCF把书读薄(4)——事务编程与可靠会话
    WCF把书读薄(3)——数据契约、消息契约与错误契约
    WCF把书读薄(2)——消息交换、服务实例、会话与并发
    Backbone.js developer 武汉 年薪8w-10w
    Java面试
    从pb文件中恢复计算图并在tensorboard中展示
    Ubuntu下解决u盘变成只读模式
  • 原文地址:https://www.cnblogs.com/zxhl/p/6071938.html
Copyright © 2011-2022 走看看