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

    C. Milking cows

        题意:有n头奶牛,横着占城一排,0表示奶牛的头朝左,1表示奶牛的头朝右,每只奶牛身上有无线的奶,现在需要对每只内牛挤奶,假设对奶牛i挤奶,看到这只奶牛的奶牛会流失1个奶,被挤过的奶牛不会流失,问挤完n只奶牛,最少会流失多少奶。

        思路:从左向右处理ai为1的前缀和,从右到左处理ai为0的前缀和,因为最优的挤奶方法肯定是,先把一种内牛挤完,并且使同种奶牛不会受到惊吓,如果同种奶牛受到惊吓肯定不是最优的,然后分别处理从左向右挤种类为1的奶牛,从右向左种类为0的奶牛,对两种答案取最小值

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e5 + 7;
    int a[maxn], L[maxn], R[maxn];
    
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; i++) {
            L[i] = L[i - 1] + (a[i] == 1);
        }
        for(int i = n; i; i--) {
            R[i] = R[i + 1] + (a[i] == 0);
        }
        long long ans1 = 0, ans2 = 0;
        for(int i = 1; i <= n; i++) if(a[i] == 1) ans1 += R[i];
        for(int i = n; i; i--) if(a[i] == 0) ans2 += L[i];
        cout << min(ans1, ans2) << endl;
        return 0;
    }
    View Code

    D. Volcanoes

        题意:在一个n*n(1e9)的地图上,有一个人开始的时候在左上角1,1,他想走到右下角n,n,他只能向下和向右走,地图上有m(1e5)个点不能走,问这个人最少走几步可以到右下角,如果不能打印-1

        思路:把不能走的点按照y从小到大x从小到大排序,每次处理相邻两行可以走到的区间,如果有一行没有可以走到的区间就打印-1,如果可以走到最后,那么答案就是2*n-2

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 7;
    struct node
    {
        int x, y;
    }a[maxn], pre[maxn], now[maxn];
    
    int n, m;
    bool cmp(node a, node b)
    {
        if(a.y == b.y)
            return a.x < b.x;
        return a.y < b.y;
    }
    bool check()
    {
        int cnt = 1;
        pre[0].x = 1, pre[0].y = 1;
        for(int i = 0; i < m; i++) {
            if(a[i].y != a[i - 1].y + 1) {
                cnt = 1;
                pre[0].y = n;
            }
            int k;
            for(k = i + 1; a[k].y == a[i].y; k++);
            k--;
            int num = 0;
            int res = 0;
            for(int j = i; j <= k; j++) {
                if(a[j].x > res + 1) {
                    now[num].x = res + 1;now[num].y = a[j].x - 1;
                    num ++;
                }
                res = a[j].x;
            }
            if(n > res) {
                now[num].x = res + 1; now[num].y = n; num++;
            }
    
    
    
    
            int t = 0;
            for(int j = 0; j < cnt; j++) {
                while(now[t].x <= pre[j].y && t < num) {
                    if(now[t].y >= pre[j].x) {
                        now[t].x = max(now[t].x, pre[j].x);
                    }
                    else {
                        now[t].x = -1; now[t].y = -1;
                    }
                    t++;
                }
                if(t > num)break;
            }
            cnt = 0;
            for(int j = 0; j < t; j++) {
                if(now[j].x != -1 && now[j].y != -1) {
                    pre[cnt].x = now[j].x; pre[cnt].y = now[j].y;
                    cnt++;
                }
            }
            if(cnt == 0) return false;
            i = k;
        }
        if(a[m - 1].y != n) return true;
        if(pre[cnt - 1].y == n) return true;
        return false;
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            a[i].x = x; a[i]. y = y;
        }
        sort(a, a + m, cmp);
        if(check()) printf("%d
    ", 2 * n - 2);
        else puts("-1");
        return 0;
    }
    View Code

    E. Propagating tree

        题意:给n(2e5)个数,有两种操作

        1 x v 表示给点x加上权值v,在x的子节点中,和x奇偶性相同的加上权值v,奇偶性不同的减去权值v

        2 x 表示询问点x的权值是多少

        思路:先进行dfs序预处理,建立两颗线段树,如果他在奇数层,就在奇数层+val,偶数层-val,分别插在不同的两棵线段树中,查询直接查询那个数的奇偶性所在的线段树

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    const int maxn = 200000 + 7;
    int tree[2][maxn << 2];
    LL lazy[2][maxn << 2];
    int n, m;
    struct node
    {
        int nxt, to;
    };
    node Edge[maxn << 2];
    int cnt = 0, ti = 0;
    int head[maxn];
    int dep[maxn], a[maxn];
    int in[maxn], out[maxn];
    void addedge(int u, int v)
    {
        Edge[cnt].to = v;
        Edge[cnt].nxt = head[u];
        head[u] = cnt++;
    }
    void dfs(int now, int pre)
    {
        dep[now] = dep[pre] + 1;
        in[now] = ++ ti;
        for(int i = head[now]; ~i; i = Edge[i].nxt) {
            int v = Edge[i].to;
            dfs(v, now);
        }
        out[now] = ti;
    }
    void pushdown(int rt, int dp, int len)
    {
        tree[dp][rt << 1] += lazy[dp][rt] * (len - (len >> 1));
        lazy[dp][rt << 1] += lazy[dp][rt];
        tree[dp][rt << 1 | 1] += lazy[dp][rt] * (len >> 1);
        lazy[dp][rt << 1 | 1] += lazy[dp][rt];
        lazy[dp][rt] = 0;
    }
    void update(int L, int R, int val, int dp, int rt, int l, int r)
    {
        if(L <= l && r <= R) {
            tree[dp][rt] += val;
            lazy[dp][rt] += val;
            return ;
        }
        if(lazy[dp][rt])
            pushdown(rt, dp, r - l + 1);
        int mid = (l + r) >> 1;
        if(L <= mid) update(L, R, val, dp, rt << 1, l, mid);
        if(R > mid) update(L, R, val, dp, rt << 1 | 1, mid + 1, r);
    }
    int query(int x, int dp, int rt, int l, int r)
    {
        if (l == r) {
            return tree[dp][rt];
        }
        if(lazy[dp][rt])
            pushdown(rt, dp, r - l + 1);
        int mid = (l + r) >> 1;
        if(x <= mid) return query(x, dp, rt << 1, l, mid);
        if(x > mid) return query(x, dp, rt << 1 | 1, mid + 1, r);
    }
    int main()
    {
        cnt = 0; ti = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        for(int i = 0; i <= n; i++) head[i] = -1;
        for(int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            addedge(u, v);
        }
        dep[0] = 0;
        dfs(1, 0);
        for(int i = 1; i <= m; i++) {
            int op;
            scanf("%d", &op);
            if(op == 1) {
                int x, val;
                scanf("%d%d", &x, &val);
                update(in[x], out[x], val, dep[x]&1, 1, 1, n);
                update(in[x] + 1, out[x], -val, !(dep[x]&1), 1, 1, n);
            }
            else {
                int x;
                scanf("%d", &x);
                printf("%d
    ",query(in[x], dep[x]&1, 1, 1, n) + a[x]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    具有快表的地址变换机构
    npm更换淘宝镜像
    内存扩充技术
    内存管理的概念
    内存的基础知识
    102. 二叉树的层序遍历
    104. 二叉树的最大深度
    206. 反转链表
    mysql 多字段查询,全局搜素
    java 处理html转义字符
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/10432656.html
Copyright © 2011-2022 走看看