1. 程式人生 > >Educational Codeforces Round 37 A B C F (暫時)

Educational Codeforces Round 37 A B C F (暫時)

n) body else if 並查集 fine namespace push swap har

A. water the garden

Code

#include <bits/stdc++.h>
#define maxn 210
using namespace std;
typedef long long LL;
int n, k;
bool vis[maxn];
int x[maxn];
bool ok() {
    for (int i = 1; i <= n; ++i) if (!vis[i]) return false;
    return true;
}
void work() {
    scanf("%d%d", &n,&k);
    memset(vis, 0, sizeof vis);
    for (int i = 0; i < k; ++i) scanf("%d", &x[i]);
    int cnt = 0;
    while (true) {
        if (ok()) { printf("%d\n", cnt); return; }
        for (int i = 0; i < k; ++i) {
            int p1 = max(0, x[i]-cnt),
                p2 = min(n, x[i]+cnt);
            vis[p1] = vis[p2] = true;
        }
        ++cnt;
    }
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) work();
    return 0;
}

B. Tea Queue

題意

若幹個人排隊等茶喝,每個人有到達時間和離去時間,每個時刻只能一個人喝茶。

問每個人喝到茶的時間。

思路

排序,然後按順序模擬(將當前時間逐個向後推移)

Code

#include <bits/stdc++.h>
#define maxn 1010
using namespace std;
typedef long long LL;
struct node {
    int l, r, id;
}a[maxn];
int ans[maxn];
bool cmp(node a, node b) {
    return (a.l < b.l) || (a.l==b.l && a.id<b.id);
}
void work() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d%d", &a[i].l, &a[i].r);
        a[i].id = i;
    }
    sort(a, a+n, cmp);
    int time = 0;
    for (int i = 0; i < n; ++i) {
        if (time <= a[i].l) {
            time = a[i].l;
            ans[a[i].id] = time;
            ++time;
        }
        else {
            if (time <= a[i].r) {
                ans[a[i].id] = time;
                ++time;
            }
            else {
                ans[a[i].id] = 0;
            }
        }
    }
    printf("%d", ans[0]);
    for (int i = 1; i < n; ++i) printf(" %d", ans[i]); puts("");
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) work();
    return 0;
}

C. Swap Adjacent Elements

題意

給出 1-n 的一個排列,只能交換相鄰兩個元素,即 \(i\)\(i+1\),且只有給定的位置 \(i\) 才可交換。

問能否通過交換得到一個升序序列。

思路

假設元素 \(a[i]\) 現在處在 \(i\) 位置,那麽交換必然通過 \(i-a[i]\) 的一整段線段,也即要求這一整段上的點都是可交換的位置。

即轉化成一個 線段覆蓋 問題,用線段樹解決。

Code

#include <bits/stdc++.h>
#define maxn 200010
#define lson (rt<<1)
#define rson (lson|1)
using namespace std;
typedef long long LL;
struct node { int l, r; bool flag; }tr[maxn<<2];
char s[maxn];
int a[maxn];
void build(int rt, int l, int r) {
    tr[rt].l = l, tr[rt].r = r;
    if (l == r) {
        tr[rt].flag = s[l] == '1'; return;
    }
    int mid = l+r>>1;
    build(lson, l, mid); build(rson, mid+1, r);
    tr[rt].flag = tr[lson].flag & tr[rson].flag;
}
bool query(int rt, int l, int r) {
    if (tr[rt].l==l&&tr[rt].r==r) return tr[rt].flag;
    int mid = tr[rt].l+tr[rt].r >> 1;
    if (r <= mid) return query(lson, l, r);
    else if (l > mid) return query(rson, l, r);
    else return query(lson, l, mid) & query(rson, mid+1, r);
}
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    scanf("%s", s+1);
    build(1, 1, n);
    for (int i = 1; i <= n; ++i) {
        if (i == a[i]) continue;
        if (i < a[i] && !query(1, i, a[i]-1)) { puts("NO"); return 0; }
        else if (i > a[i] && !query(1, a[i], i-1)) { puts("NO"); return 0; }
    }
    puts("YES");
    return 0;
}

F. SUM and REPLACE

題意

對一個序列進行兩種操作:

  1. \([l,r]\) 中每個數 \(x\) 變為其約數個數 \(D(x)\)
  2. \([l,r]\) 區間求和

思路

神似 bzoj 3211 花神遊歷各國

Code

Ver. 1:線段樹

#include <bits/stdc++.h>
#define maxn 300010
#define maxl 1000010
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
typedef long long LL;
int prime[maxn], d[maxl], cnt[maxl], n, k, a[maxn];
bool check[maxl];
void init() {
    int tot = 0; d[1] = 1;
    for (int i = 2; i <= 1000000; ++i) {
        if (!check[i]) {
            prime[tot++] = i;
            d[i] = 2, cnt[i] = 1;
        }
        for (int j = 0; j < tot; ++j) {
            if (i * prime[j] > 1000000) break;
            check[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                cnt[i * prime[j]] = cnt[i] + 1;
                d[i * prime[j]] = d[i] / (cnt[i] + 1) * (cnt[i * prime[j]] + 1);
                break;
            }
            cnt[i * prime[j]] = 1;
            d[i * prime[j]] = d[i] << 1;
        }
    }
}
struct node { int l, r; bool flag; LL sum; } tr[maxn<<2];
inline void push_up(int rt) {
    tr[rt].sum = tr[lson].sum + tr[rson].sum;
    tr[rt].flag = tr[lson].flag & tr[rson].flag;
}
inline int midi(int a, int b) { return a + b >> 1; }
void build(int rt, int l, int r) {
    tr[rt].l = l, tr[rt].r = r, tr[rt].flag = 0;
    if (l == r) {
        scanf("%I64d", &tr[rt].sum);
        if (tr[rt].sum <= 2) tr[rt].flag = 1;
        return;
    }
    int mid = midi(l,r);
    build(lson, l, mid); build(rson, mid + 1, r);
    push_up(rt);
}
void modify(int rt, int l, int r) {
    if (tr[rt].flag) return;
    if (tr[rt].l == tr[rt].r) {
        tr[rt].sum = d[tr[rt].sum];
        if (tr[rt].sum <= 2) tr[rt].flag = 1;
        return;
    }
    int mid = midi(tr[rt].l, tr[rt].r);
    if (r <= mid) modify(lson, l, r);
    else if (l > mid) modify(rson, l, r);
    else { modify(lson, l, mid); modify(rson, mid + 1, r); }
    push_up(rt);
}
LL query(int rt, int l, int r) {
    if (tr[rt].l == l && tr[rt].r == r) return tr[rt].sum;
    int mid = midi(tr[rt].l, tr[rt].r);
    if (r <= mid) return query(lson, l, r);
    else if (l > mid) return query(rson, l, r);
    else return query(lson, l, mid) + query(rson, mid + 1, r);
}
int main() {
    scanf("%d%d", &n,&k);
    build(1, 1, n);
    init();
    while (k--) {
        int t, l, r;
        scanf("%d%d%d", &t,&l,&r);
        if (t==2) printf("%I64d\n", query(1, l, r));
        else modify(1, l, r);
    }
    return 0;
}

Ver. 2:樹狀數組+並查集

#include <bits/stdc++.h>
#define maxn 300010
#define maxl 1000010
using namespace std;
typedef long long LL;
int prime[maxn], d[maxl], cnt[maxl], fa[maxn], n, k, a[maxn];
bool check[maxl];
LL c[maxn];
void init() {
    int tot = 0; d[1] = 1;
    for (int i = 2; i <= 1000000; ++i) {
        if (!check[i]) {
            prime[tot++] = i;
            d[i] = 2, cnt[i] = 1;
        }
        for (int j = 0; j < tot; ++j) {
            if (i * prime[j] > 1000000) break;
            check[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                cnt[i * prime[j]] = cnt[i] + 1;
                d[i * prime[j]] = d[i] / (cnt[i] + 1) * (cnt[i * prime[j]] + 1);
                break;
            }
            cnt[i * prime[j]] = 1;
            d[i * prime[j]] = d[i] << 1;
        }
    }
}
int lowbit(int x) { return x & (-x); }
void add(int p, int x) {
    while (p <= n) c[p] += x, p += lowbit(p);
}
LL query(int x) {
    LL ret = 0;
    while (x) ret += c[x], x -= lowbit(x);
    return ret;
}
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
int main() {
    init();
    scanf("%d%d", &n,&k);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        add(i, a[i]);
        fa[i] = i;
    }
    fa[n+1] = n+1;
    for (int i = 1; i <= n; ++i) if (a[i] <= 2) fa[i] = find(i+1);
    while (k--) {
        int t, l, r;
        scanf("%d%d%d", &t,&l,&r);
        if (t==2) printf("%I64d\n", query(r)-query(l-1));
        else for (int i = find(l); i <= r; i = find(i+1)) {
            add(i, d[a[i]] - a[i]);
            if ((a[i] = d[a[i]]) <= 2) fa[i] = find(i+1);
        }
    }
    return 0;
}

Educational Codeforces Round 37 A B C F (暫時)