码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #379 (Div. 2)

时间:2016-11-17 00:56:06      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:sort   display   tar   二分   from   pair   方法   continue   typedef   

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\n",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

 

Codeforces Round #379 (Div. 2)

标签:sort   display   tar   二分   from   pair   方法   continue   typedef   

原文地址:http://www.cnblogs.com/zxhl/p/6071938.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!