zoukankan      html  css  js  c++  java
  • CodeForces Round #514 (div2)

    A:Cashier

    题意:问可以休息多少次。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    int n, L, a;
    int t[N], l[N];
    int main(){
        scanf("%d%d%d", &n, &L, &a);
        for(int i = 1; i <= n; ++i)
            scanf("%d%d", &t[i], &l[i]);
        t[n+1] = L;
        t[0] = l[0] = 0;
        int ans = 0;
        for(int i = 0; i <= n; ++i){
            int dif = t[i+1] - t[i] - l[i];
            ans += dif/a;
        }
        cout << ans << endl;
        return 0;
    }
    View Code

    B:B - Forgery

    题意:一次能给边上一圈填上'#',问这个图形合法不合法。填的时候不能越界。

    直接去check行不行就好啦。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e3 + 100;
    char s[N][N];
    int dx[8] = {0,0,0,1,1,2,2,2};
    int dy[8] = {0,1,2,0,2,0,1,2};
    int n, m;
    bool in(int x, int y){
        if(x < 1 || x > n) return false;
        if(y < 1 || y > m) return false;
        return true;
    }
    bool check2(int x, int y){
        for(int i = 0; i < 8; ++i){
            int xx = x + dx[i];
            int yy = y + dy[i];
            if(!in(xx,yy) || s[xx][yy] != '#') return false;
        }
        return true;
    }
    bool check(int x, int y){
        for(int b = 0; b < 8; ++b){
            if(check2(x-dx[b], y-dy[b]))  return true;
        }
        return false;
    }
    int main(){
    
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) scanf("%s", s[i]+1);
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j){
                if(s[i][j] == '#'){
                    if(!check(i,j)){
                        puts("NO");
                        return 0;
                    }
                }
        }
        puts("YES");
        return 0;
    }
    View Code

    C:C - Sequence Transformation

    题意:给你[1,n]的数,每次会输出整个序列的gcd,然后可以删除一个数,然后问gcd的字典序排列最大是多少。

    题解:发现 如果存在奇数,然后我们就会导致 gcd恒为1。 那么我们肯定是先删除奇数。 

    然后把奇数删完了之后,剩下了2,4,6,8,我们把这些数都/2,变成了新的1,2,3,4,然后再删除奇数就ok了。递归解决问题。

    然后就是 如果出现了 1, 2, 3。 那么肯定是按照顺序删除 1 2 3最好了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    int n;
    vector<int> vc;
    void dfs(int k, int n){
        if(n == 0) return ;
        if(n == 3){
            printf("%d %d %d", k, k, k*3);
            return ;
        }
        if(n == 1){
            printf("%d ", k);
            return ;
        }
        if(n == 2){
            printf("%d %d", k, 2*k);
            return ;
        }
        for(int i = 1; i <= n; i += 2){
            printf("%d ", k);
        }
        dfs(k*2, n/2);
    }
    int main(){
        scanf("%d", &n);
        dfs(1, n);
        return 0;
    }
    View Code

    D:D - Nature Reserve

    题意:有n个保护动物,然后就是让你画一个○,使得所有的动物都在圈内,并且只有1个交点。

    不是很想多讲,二分乱搞就好了,注意精度。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    pll p[N];
    int n, f1 = 0, f2 = 0;
    double eps = 1e-9;
    bool check2(double x1, double y1, double x2, double y2){
        long double len = y2;
        len *= len;
        long double dis = (long double)(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
        return len >= dis;
    }
    bool check(double len){
        double lp = -1e7, rp = 1e7;
        for(int i = 1; i <= 100; ++i){
            int lsz = 0, rsz = 0;
            double mid = (lp+rp) / 2;
            for(int k = 1; k <= n; ++k){
                if(check2(p[k].fi,p[k].se,mid,len));
                else if(p[k].fi <= mid ) lsz++;
                else rsz++;
            }
            if(lsz && rsz) return false;
            if(lsz+rsz == 0) return true;
            if(lsz) rp = mid;
            else lp = mid;
        }
        return false;
    }
    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i){
            scanf("%d%d", &p[i].fi, &p[i].se);
            if(p[i].se > 0) ++f1;
            else ++f2, p[i].se = -p[i].se;
        }
        if(f1 && f2){
            puts("-1");
            return 0;
        }
        double l = 0, r = 1e15;
        for(int i = 1; i <= 100; ++i){
            double mid = (l+r)/2;
            if(check(mid)) r = mid;
            else l = mid;
        }
        printf("%.10f", r);
        return 0;
    }
    View Code

    E:Split the Tree

    题意:给定1棵以1为根的树,让你将这棵数分成竖着的几条链,问链最少是多少条,并且每一条链要求点的个数少于L,路径之和少于S。

    题解:

    从叶子网上爬,然后通过二分和倍增查看最多能到哪里,然后将这个点指到可以去的那个点为止。

    然后不是叶子就接受叶子传上来的最远可以到哪里,如果到不了这个点就把这个点当做新的起点继续去找,如果可以到这个点就记录下最远可以去哪里就好了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    int anc[N][20];
    int a[N];
    LL sum[N];
    int n, l; LL S;
    vector<int> vc[N];
    int deep[N];
    void dfs(int o){
        for(int x : vc[o]){
            deep[x] = deep[o] + 1; sum[x] = sum[o] + a[x];
            anc[x][0] = o;
            for(int i = 1; i < 19; ++i)
                anc[x][i] = anc[anc[x][i-1]][i-1];
            dfs(x);
        }
    }
    int get(int o, int k){
        for(int i = 19; i >= 0; --i){
            if((k>>i)&1) o = anc[o][i];
        }
        return o;
    }
    int to[N];
    int ans;
    int Find(int o){
        int ll = 1, rr = l;
        while(ll <= rr){
            int mid = ll+rr >> 1;
            int p = get(o, mid);
            if(sum[o]-sum[p] <= S) ll = mid+1;
            else rr = mid-1;
        }
        return get(o, ll-1);
    }
    void solve(int o){
        to[o] = -1;
        for(int x : vc[o]){
            solve(x);
            if(to[x] == -1 || deep[to[x]] >= deep[o]) continue;
            if(to[o] == -1) to[o] = to[x];
            else if(deep[to[o]] > deep[to[x]]) to[o] = to[x];
        }
        if(to[o] == -1) ans++, to[o] = Find(o);
    }
    int main(){
        scanf("%d%d%lld", &n, &l, &S);
        for(int i = 1; i <= n; ++i){
            scanf("%d", &a[i]);
            if(a[i] > S){
                puts("-1");
                return 0;
            }
        }
        for(int i = 2,v; i <= n; ++i){
            scanf("%d", &v);
            vc[v].pb(i);
        }
        sum[1] = a[1]; deep[1] = 1;
        dfs(1); solve(1);
        cout << ans << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    OI数学知识清单
    线段树入门教程
    扩展欧几里得定理基础讲解 代码及证明
    名字竞技场 V3.0
    可持久化线段树(主席树)新手向教程
    矩阵乘法浅析
    [Luogu] P1233 木棍加工
    高斯消元 模板
    位运算技巧
    [ZJOJ] 5794 2018.08.10【2018提高组】模拟A组&省选 旅行
  • 原文地址:https://www.cnblogs.com/MingSD/p/10120146.html
Copyright © 2011-2022 走看看