• NOIP 模拟赛


          NOIP 模拟赛

    思路:求 n , m 的 gcd,然后用 n , m 分别除以 gcd;若 n 或 m 为偶数,则输出 1/2.

      特别的,当 n = m = 1 时,应输出 1/1

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    LL n, m;
    
    LL gcd(LL x, LL y) {
        return y == 0 ? x : gcd(y, x % y);
    }
    
    int main() {
        freopen("line.in","r",stdin);
        freopen("line.out","w",stdout);
        cin >> n >> m;
        if (n == m && m == 1) return printf("1/1
    "), 0;
        LL tmp = gcd(n, m);
        n /= tmp; m /= tmp;
        if (!(n & 1) || !(m & 1)) return printf("1/2
    "), 0;
        
        fclose(stdin); fclose(stdout);
        return 0;
    }
    考场代码

    正解:题目要求的是比值,故当 m 与 n 不互质时,我们可以求出 m 和 n 的最大公约数 d,并将 m /= d, n /= d,并不影响结果。故我们现在假定 m 和 n 互质。若m 和 n 中有一个为偶数, 那么根据对称性, 答案就是 1/2。 如果 m 和 n 均为奇数,那么答案就是(n*m+1) / (2*m*n)。

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    LL n, m, d;
    
    LL gcd(LL x, LL y) {
        return x % y ? gcd(y, x % y) : y;
    }
    
    int main() {
        freopen("line.in","r",stdin);
        freopen("line.out","w",stdout);
        cin >> n >> m;
        d = gcd(n, m);
        n /= d, m /= d;
        if ((n + m) & 1) cout << "1/2" << endl;
        else cout << (n * m + 1) / 2 << "/" << n * m << endl;
        return 0;
    }
    正解

    思路:线段树维护是否有浓雾。一开始都没有,建树时每个位置的值都赋为 1;若进行 1 或 2 操作,用 flag 标记,因为是区间直接赋值,所以两种操作只需要一个标记即可。查询写错了,导致100 -> 10,对题意理解稍有偏差。

    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int N = 100005;
    int n, m, k, x, y;
    struct nond {
        int ll, rr;
        int sum;
        int flag;
    } tree[N << 2];
    
    inline void update(int now) {
        tree[now].sum = tree[now << 1].sum + tree[now << 1 | 1].sum;
    }
    
    inline void down(int now) {
        if (tree[now].flag == 1) {
            tree[now << 1].flag = 1;
            tree[now << 1 | 1].flag = 1;
            tree[now << 1].sum = tree[now << 1].rr - tree[now << 1].ll + 1;
            tree[now << 1 | 1].sum = tree[now << 1 | 1].rr - tree[now << 1 | 1].ll + 1;
        }
        else {
            tree[now << 1].flag = -1;
            tree[now << 1 | 1].flag = -1;
            tree[now << 1].sum = 0;
            tree[now << 1 | 1].sum = 0;
        }
        tree[now].flag = 0;
        return ;
    }
    
    inline void build(int now, int l, int r) {
        tree[now].ll = l; tree[now].rr = r;
        tree[now].flag = 0; tree[now].sum = 1;
        if (l == r) return ;
        int mid = (l + r) >> 1;
        build(now << 1, l, mid);
        build(now << 1 | 1, mid + 1, r);
        update(now);
    }
    
    inline void change(int now, int l, int r) {
        if (tree[now].ll == l && tree[now].rr == r) {
            tree[now].flag = -1;
            tree[now].sum = 0;
            return ;
        }
        if (tree[now].flag != 0) down(now);
        int mid = (tree[now].ll + tree[now].rr) >> 1;
        if (l <= mid && mid < r) change(now << 1, l, mid), change(now << 1 | 1, mid + 1, r);
        else if (r <= mid) change(now << 1, l, r);
        else change(now << 1 | 1, l, r);
        update(now);
    }
    
    inline void become(int now, int l, int r) {
        if (tree[now].ll == l && tree[now].rr == r) {
            tree[now].flag = 1;
            tree[now].sum = tree[now].rr - tree[now].ll + 1;
            return ;
        }
        if (tree[now].flag != 0) down(now);
        int mid = (tree[now].ll + tree[now].rr) >> 1;
        if (l <= mid && mid < r) become(now << 1, l, mid), become(now << 1 | 1, mid + 1, r);
        else if (r <= mid) become(now << 1, l, r);
        else become(now << 1 | 1, l, r);
        update(now);
    }
    
    inline int query(int now, int l, int r) {
        if (tree[now].ll == l && tree[now].rr == r)
            return tree[now].sum;
        if (tree[now].flag != 0) down(now);
        int mid = (tree[now].ll + tree[now].rr) >> 1;
        if (l <= mid && mid < r) return query(now << 1, l, mid) + query(now << 1 | 1, mid + 1, r);
        else if (r <= mid) return query(now << 1, l, r);
        else return query(now << 1 | 1, l, r);
    }
    
    int main() {
        freopen("explore.in","r",stdin);
        freopen("explore.out","w",stdout);
        scanf("%d%d", &n, &m);
        build(1, 1, n);
        for (int i = 1; i <= m; ++i) {
            scanf("%d%d", &k, &x);
            if (k == 1) { scanf("%d", &y); change(1, x, y); }
            else if (k == 2) { scanf("%d", &y); become(1, x, y); }
            else {
                if (query(1, x, x) == 0) printf("0
    ");
                else {
                    if (query(1, 1, x) == x || query(1, x, n) == n - x + 1)
                        printf("INF
    ");
                    else for (int j = 1; j <= (n >> 1); ++j) {
                        int tmp = query(1, x - j, x + j);
                        if (tmp != j << 1 | 1) { printf("%d
    ", tmp); break; }
                    }
                }
            }
        }
        fclose(stdin); fclose(stdout);
        return 0;
    }
    考场代码
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstdlib>
    #define fortodo(i, f, t) for (i = f; i <= t; i++)
    using namespace std;
    
    int lsd[200001], rsd[200001], lsid[200001], rsid[200001], cov[200001], segsize;
    bool emp[200001];
    
    int SEG_Build(int L, int R) {
        int Nid = ++segsize;
        lsd[Nid] = L;
        rsd[Nid] = R;
        emp[Nid] = true;
        cov[Nid] = 0;
        if (L == R) lsid[Nid] = rsid[Nid] = -1;
        else {
            lsid[Nid] = SEG_Build(L, (L + R) / 2);
            rsid[Nid] = SEG_Build((L + R) / 2 + 1, R);
        };
        return Nid;
    };
    
    bool SEG_Empty(int Nid) {
        if (cov[Nid] == 0) return true;
        if (cov[Nid] == 1) return false;
        return emp[Nid];
    };
    
    void SEG_Reemp(int Nid) {
        emp[Nid] = SEG_Empty(lsid[Nid]) && SEG_Empty(rsid[Nid]);
    };
    
    void SEG_Inherit(int Nid) {
        if (cov[Nid] == -1) return;
        if (lsd[Nid] == rsd[Nid]) return;
        cov[lsid[Nid]] = cov[Nid];
        cov[rsid[Nid]] = cov[Nid];
        cov[Nid] = -1;
        SEG_Reemp(Nid);
    };
    
    void SEG_Paint(int Nid, int L, int R, int Color) {
        SEG_Inherit(Nid);
        if ((L == lsd[Nid]) && (R == rsd[Nid])) {
            cov[Nid] = Color;
            return;
        };
        int Div = (lsd[Nid] + rsd[Nid]) / 2;
        if (L >  Div) SEG_Paint(rsid[Nid], L, R, Color);
        if (R <= Div) SEG_Paint(lsid[Nid], L, R, Color);
        if ((L <= Div) && (R > Div)) {
            SEG_Paint(lsid[Nid], L, Div, Color);
            SEG_Paint(rsid[Nid], Div + 1, R, Color);
        };
        SEG_Reemp(Nid);
    };
    
    bool SEG_Query(int Nid, int L, int R) {
        SEG_Inherit(Nid);
        if (SEG_Empty(Nid)) return true;
        if ((L == lsd[Nid]) && (R == rsd[Nid])) return SEG_Empty(Nid);
        int Div = (lsd[Nid] + rsd[Nid]) / 2;
        if (L >  Div) return SEG_Query(rsid[Nid], L, R);
        if (R <= Div) return SEG_Query(lsid[Nid], L, R);
        return SEG_Query(lsid[Nid], L, Div) && SEG_Query(rsid[Nid], Div + 1, R);
    };
    
    int S, Q;
    int i, j;
    int Opt, X, Y;
    
    void Answer(int P) {
        if (!SEG_Query(1, P, P)) {
            printf("0
    ");
            return;
        };
        if ((SEG_Query(1, 1, P)) || (SEG_Query(1, P, S))) {
            printf("INF
    ");
            return;
        };
        int L, R, M, Ans[2];
        L = 2; R = P;
        while (L < R) {
            M = (L + R) / 2;
            if (SEG_Query(1, M, P)) R = M;
            else L = M + 1;
        };
        Ans[0] = L;
        L = P; R = S - 1;
        while (L < R) {
            M = (L + R + 1) / 2;
            if (SEG_Query(1, P, M))
                L = M;
            else
                R = M - 1;
        };
        Ans[1] = L;
        printf("%d
    ", Ans[1] - Ans[0] + 1);
    };
    
    int main() {
        freopen("explore.in", "r", stdin);
        freopen("explore.out", "w", stdout);
        scanf("%d%d", &S, &Q);
        segsize = 0;
        SEG_Build(1, S);
        fortodo(i, 1, Q) {
            scanf("%d%d", &Opt, &X);
            if (Opt != 3) scanf("%d", &Y);
            if (Opt == 1) SEG_Paint(1, X, Y, 1);
            if (Opt == 2) SEG_Paint(1, X, Y, 0);
            if (Opt == 3) Answer(X);
        };
        return 0;
    };
    正解

    思路:

      1.暴搜  写挂了,样例都过不了

      2.树形DP  不会写 后来讲题时发现自己想法是错的

      3.并查集  将直接连接两个有苹果的节点的边打上标记,记录边权和,但仍会存在多个苹果间接相连的情况,没有想到解决办法

    然后我就交了唯一一个过了样例但是最不靠谱的 3 

    然后就暴零了 T^T。。。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int M = 100005;
    int n, m, tot;
    int t[M], fc[M];
    int fa[M], f[M];
    struct nond {
        int u, v, w;
        int flag;
    }e[M];
    
    int find(int x) {
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    
    bool flag = false;
    inline void dfs(int now) {  //可以明显看到没写完 因为不会写了 qwq
        if (f[now] == 1) flag = 1;
        
    }
    
    long long ans;
    int main() {
        freopen("apple.in","r",stdin);
        freopen("apple.out","w",stdout);
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; ++i) fa[i] = i;
        for (int i = 1; i < n; ++i) {
            scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
            e[i].flag = 0;
        }
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &t[i]);
            f[t[i]] = 1;
        }
        for (int i = 1; i < n; ++i) {
            if (f[e[i].u] == 1 && f[e[i].v] == 1) {
                e[i].flag = 1;
                ans += e[i].w;
                ++tot;
                continue;
            }
            int x = find(e[i].u), y = find(e[i].v);
            fa[x] = y;
            
        }
        if (tot == m - 1) cout << ans;
        else {
            for (int i = 0; i < n; ++i)
                ++fc[find(i)];
            for (int i = 0; i < n; ++i) {
                if (fc[i] > 1) dfs(i);
                if (tot == m - 1) break;
            }
            cout << ans;
        }
        fclose(stdin); fclose(stdout);
        return 0;
    }
    考场代码

    正解:

      

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <cmath>
    #define REP(i, n) for (int i = 0; i < (n); ++i)
    #define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
    #define ROF(i, a, b) for (int i = (a); i >= (b); --i)
    #define FEC(p, u) for (edge *p = G.head[u]; p; p = p->nxt)
    using namespace std;
    typedef long long LL;
    LL inf = 1LL<<60;
    
    int n, rt;
    bool a[200000];
    LL f[200000], g[200000];
    
    struct edge {
        int b, len;
        edge *nxt;
    } e[300000], *le;
    struct graph {
        edge *head[200000];
        void init() {
            le = e;
            REP(i, n) head[i] = NULL;
        }
        void add(int x, int y, int z) {
            le->b = y, le->len = z, le->nxt = head[x], head[x] = le++;
        }
    } G;
    
    int fa[200000];
    LL pre[200000];
    int q[200000];
    void init() {
        int k, u, v, w;
        scanf("%d%d", &n, &k);
        G.init();
        REP(i, n-1) {
            scanf("%d%d%d", &u, &v, &w);
            G.add(u, v, w);
            G.add(v, u, w);
        }
        while (k--) {
            scanf("%d", &u);
            a[u] = true;
        }
        rt = u;
    }
    
    void bfs() {
        int R = 0;
        q[0] = rt;
        REP(L, n)
        FEC(p, q[L]) if (p->b != fa[q[L]]) {
            fa[p->b] = q[L];
            pre[p->b] = p->len;
            q[++R] = p->b;
        }
    }
    
    void work() {
        ROF(i, n - 1, 0) {
            int x = q[i];
            if (a[x]) {
                FEC(p, x) if (p->b != fa[x]) g[x] += f[p->b];
                f[x] = g[x]+pre[x];
            }
            else {
                FEC(p, x) if (p->b != fa[x])    f[x] += f[p->b];
                g[x] = inf;
                FEC(p, x) if (p->b != fa[x]) g[x] = min(g[x], f[x] - f[p->b] + g[p->b]);
                f[x] = min(f[x], g[x]+pre[x]);
            }
        }
    }
    
    int main() {
        freopen("apple.in", "r", stdin);
        freopen("apple.out", "w", stdout);
        init();
        bfs();
        work();
        cout << f[rt] << endl;
        return 0;
    }
    正解
  • 相关阅读:
    隐式图回溯法之八皇后问题解答
    试用O(n)来实现求出一个无序数组的中位数
    C++学习第一弹: const 指针 引用答疑
    一道面试题的解答_骑士获得金币问题
    根据已知词表选出好词(直通车)
    python3.5爬虫完成笔趣阁小说的爬取
    关于_水木社区[日经题]_10只狗鉴别1000瓶中哪一瓶药有毒_的解答思路
    数据库想法整合,多表联立交互
    [网络推广]直通车学习
    3行实现模糊匹配
  • 原文地址:https://www.cnblogs.com/v-vip/p/9780853.html
Copyright © 2020-2023  润新知