NOIP 模擬賽

      NOIP 模擬賽ios

思路:求 n , m 的 gcd,而後用 n , m 分別除以 gcd;若 n 或 m 爲偶數,則輸出 1/2.app

  特別的,當 n = m = 1 時,應輸出 1/1ide

#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\n"), 0;
    LL tmp = gcd(n, m);
    n /= tmp; m /= tmp;
    if (!(n & 1) || !(m & 1)) return printf("1/2\n"), 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)。ui

#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,對題意理解稍有誤差。spa

#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\n");
            else {
                if (query(1, 1, x) == x || query(1, x, n) == n - x + 1)
                    printf("INF\n");
                else for (int j = 1; j <= (n >> 1); ++j) {
                    int tmp = query(1, x - j, x + j);
                    if (tmp != j << 1 | 1) { printf("%d\n", 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\n");
        return;
    };
    if ((SEG_Query(1, 1, P)) || (SEG_Query(1, P, S))) {
        printf("INF\n");
        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\n", 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;
};
正解

 

思路:3d

  1.暴搜  寫掛了,樣例都過不了code

  2.樹形DP  不會寫 後來說題時發現本身想法是錯的blog

  3.並查集  將直接鏈接兩個有蘋果的節點的邊打上標記,記錄邊權和,但仍會存在多個蘋果間接相連的狀況,沒有想到解決辦法ci

而後我就交了惟一一個過了樣例可是最不靠譜的 3 string

而後就暴零了 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;
}
正解
相關文章
相關標籤/搜索