Codeforces #310(div2)

A. Case of the Zeros and Ones

题意: 我爱消除 - - 相邻的01就会被消除 问最后能剩下多少~

思路: 仔细观察我们发现 只要存在不相同的数 那么它们一定会被消除 最后一定为全0或者全1序列

那么答案就是abs(n_'0' - n_'1')了

参考code:

//
//  Created by TaoSama on 2015-06-27
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n;
string s;

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> n >> s) {
		int cnt = 0;
        for(int i = 0; i < n; ++i)
			if(s[i] == '0') ++cnt;
		cout << abs(n - 2 * cnt) << '\n';
    }
    return 0;
}

B. Case of Fake Numbers

题意: 有一些gear 它们的tooth是 逆时针0-n-1放置的 奇数位置的是逆时针转 偶数位置是顺时针 问同时转多少次 可以使得序列变成0-n-1

思路: 枚举两个gear的合法状态 判断后面的gear是否合法 根据鸽笼原理 枚举n^2次就够了 (据说n次就可以了?)

参考code:

//
//  Created by TaoSama on 2015-06-27
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, a[1005];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> n) {
        for(int i = 1; i <= n; ++i) cin >> a[i];
        if(n == 1) {
            cout << "YES\n";
            continue;
        }
        bool ok = false;
        for(int t = 0; t <= 1e7; ++t) {
            int x = (a[1] + t) % n, y = ((a[2] - t) % n + n) % n;
            if(x == 0 && y == 1) {
                bool can = true;
                for(int i = 3; i <= n; i ++) {
                    if(i & 1) {
                        int x = (a[i] + t) % n;
                        if(x != i - 1) {
                            can = false;
                            break;
                        }
                    } else {
                        int y = ((a[i] - t) % n + n) % n;
                        if(y != i - 1) {
                            can = false;
                            break;
                        }
                    }
                }
                if(can) {
                    ok = true;
                    break;
                }
            }
        }
        cout << (ok ? "YES" : "NO") << endl;
    }
    return 0;
}

C. Case of Matryoshkas

题意: 俄罗斯套娃 - - 反正 仔细读题吧  最后就是求1开头的链有多长 其它的都要拆开

思路: 题读懂大家应该都会 - -

参考code: 

//
//  Created by TaoSama on 2015-06-27
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, k;
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> n >> k) {
        long long Max = 1, idx, ans = 0;
        for(int i = 1; i <= k; ++i) {
            int m; cin >> m;
            a[i].clear();
            for(int j = 1; j <= m; ++j) {
                int x; cin >> x;
                a[i].push_back(x);
            }
        }
        for(int i = 1; i <= k; ++i) {
            int cnt = 1;
            if(a[i][0] == 1) {
                idx = i;
                for(int j = 1; j < a[i].size(); ++j) {
                    if(a[i][j] - a[i][j - 1] == 1) ++Max;
                    else break;
                }
            }
            ans += a[i].size() - 1;
        }
        long long sum = n - Max + 1;
        ans = ans - (a[idx].size() - 1) + (a[idx].size() - Max) + sum - 1;
        cout << ans << endl;
    }
    return 0;
}


D. Case of Fugitive

题意: 给相邻的岛放桥 然后相邻岛的距离范围 给出了计算公式 其实就是[l2 - r1, r2 - l1]这个区间 然后看能不能放 可以输出放的姿势

思路: 贪心 两种思路都行 如果降序排序l,r 那么每次对于r找一个满足它的最大的桥 然后判断这个桥满不满足l 

必须每个岛间都找到桥 找不到就是no 记录一下桥就好了

当然升序类似~ - - 

参考code:

//
//  Created by TaoSama on 2015-06-28
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

typedef long long LL;
pair<pair<LL, LL>, int> a[N];
set<pair<LL, int> > s;
int n, m, ans[N];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> n >> m) {
        LL _l, _r, l, r;
        cin >> _l >> _r;
        for(int i = 1; i < n; ++i) {

            cin >> l >> r;
            a[i] = {{_r - l, _l - r}, i};
            _l = l, _r = r;
        }
        s.clear();
        for(int i = 1; i <= m; ++i) {
            LL x; cin >> x;
            s.insert({x, i});
        }
        sort(a + 1, a + n);

        bool ok = true;
        for(int i = 1; i < n; ++i) {
            LL l = -a[i].first.first, r = -a[i].first.second;
            auto k = s.lower_bound({r, INF});
            if(k == s.begin()) {
                ok = false;
                break;
            }
            k--;
            if(k->first < l) {
                ok = false;
                break;
            }
            ans[a[i].second] = k->second;
            s.erase(k);
        }
        if(ok) {
            cout << "Yes\n";
            for(int i = 1; i < n; ++i)
                cout << ans[i] << ' ';
            cout << '\n';
        } else cout << "No\n";
    }
    return 0;
}

E. Case of Chocolate

题意: 每次从主对角线的一个位置出发 吃一列或者一行 如果碰到吃过的或者出边界  就不能吃了 问每次吃多少个

思路: 


n = 10^9很大 - - 所以先离线然后离散化坐标~   维护两棵线段树 X和Y  X表示被吃的格子的最大的y坐标 Y同理  一开始都是0

这样 举个例子 比如 3 4 U 查询X(x = 3)得到这个max是0 然后ans = y - max = 4 - 0 = 4 然后用x = 3更新Y的[max = 0, y = 4]的区间

下次查询6 1 L 查询Y(y = 1)得到这个max是刚才的3 然后ans = x - max = 6 - 3 = 3  然后用y = 1更新X的[max = 3, x = 6]的区间

这样就ok了 可以动态建树不用离散化 改天补 然后set也可以搞

参考code:

//
//  Created by TaoSama on 2015-06-28
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

struct SegTree {
    int Max[N * 6], lazy[N * 6];

    void push_up(int rt) {
        Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
    }

    void push_down(int rt) {
        if(~lazy[rt]) {
            Max[rt << 1] = max(Max[rt << 1], lazy[rt]);
            Max[rt << 1 | 1] = max(Max[rt << 1 | 1], lazy[rt]);
            lazy[rt << 1] = max(lazy[rt << 1], lazy[rt]);
            lazy[rt << 1 | 1] = max(lazy[rt << 1 | 1], lazy[rt]);
            lazy[rt] = -1;
        }
    }

    void build(int l, int r, int rt) {
        Max[rt] = 0; lazy[rt] = -1;
        if(l == r) return;
        int m = l + r >> 1;
        build(lson);
        build(rson);
        push_up(rt);
    }

    void update(int L, int R, int v, int l, int r, int rt) {
        if(L <= l && r <= R) {
            lazy[rt] = max(lazy[rt], v);
            Max[rt] = max(Max[rt], lazy[rt]);
            return;
        }
        int m = l + r >> 1;
        push_down(rt);
        if(L <= m) update(L, R, v, lson);
        if(R > m) update(L, R, v, rson);
        push_up(rt);
    }

    int query(int o, int l, int r, int rt) {
        if(l == r) return Max[rt];
        int m = l + r >> 1;
        push_down(rt);
        if(o <= m) return query(o, lson);
        else return query(o, rson);
    }
};

SegTree X, Y;
int n, q;
int ox[N], oy[N];
bool vx[N], vy[N];
char op[N][2];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d%d", &n, &q) == 2) {
        memset(vx, false, sizeof vx);
        memset(vy, false, sizeof vy);
        vector<int> xs, ys;
        for(int i = 1; i <= q; ++i) {
            scanf("%d%d%s", ox + i, oy + i, op[i]);
            xs.push_back(ox[i]);
            ys.push_back(oy[i]);
        }
        sort(xs.begin(), xs.end());
        sort(ys.begin(), ys.end());
        xs.resize(unique(xs.begin(), xs.end()) - xs.begin());
        ys.resize(unique(ys.begin(), ys.end()) - ys.begin());
        X.build(1, xs.size(), 1); Y.build(1, ys.size(), 1);

        for(int i = 1; i <= q; ++i) {
            int x = lower_bound(xs.begin(), xs.end(), ox[i]) - xs.begin() + 1;
            int y = lower_bound(ys.begin(), ys.end(), oy[i]) - ys.begin() + 1;
//            pr(x); prln(y);
            if(*op[i] == 'U') {
                if(vx[x]) {
                    puts("0");
                    continue;
                }
                vx[x] = true;
                int Max = X.query(x, 1, xs.size(), 1);
//                pr(Max);
                printf("%d\n", oy[i] - Max);
                int k = lower_bound(ys.begin(), ys.end(), Max) - ys.begin() + 1;
//                pr(k); prln(ox[i]);
                Y.update(k, y, ox[i], 1, ys.size(), 1);
            } else {
                if(vy[y]) {
                    puts("0");
                    continue;
                }
                vy[y] = true;
                int Max = Y.query(y, 1, ys.size(), 1);
//                pr(Max);
                printf("%d\n", ox[i] - Max);
                int k = lower_bound(xs.begin(), xs.end(), Max) - xs.begin() + 1;
//                pr(k); prln(oy[i]);
                X.update(k, x, oy[i], 1, xs.size(), 1);
            }
        }
    }
    return 0;
}

实在是不想写了 - - 这几天有点烦 - - 唉 - - 贴个别人写的吧~ 反正大概是这样~ 动态建树:

/*
    Author: Zhouxing Shi
    Created on Jun27, 2015
*/
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define drep(i, a, b) for (int i = (a); i >= (b); --i)
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define pb(x) push_back(x)
#define mp(x, y) (make_pair(x, y))
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
const int inf = ~0U >> 1;
const ll INF = ~0ULL >> 1;
//***************************

map<pii, int> h;

int N, Q, x, y;
char dir[10];

struct node {
    node *ls, *rs;
    int m, lazy;
    node() { ls = rs = NULL; m = lazy = 0; }
    void cover(int d) {
        m = max(m, d);
        lazy = max(lazy, d);
    }
    void push() {
        if(!ls) ls = new node();
        if(!rs) rs = new node();
        ls->cover(lazy);
        rs->cover(lazy);
        lazy = 0;
    }
    void upd() {
        m = 0;
        if(ls) m = max(m, ls->m);
        if(rs) m = max(m, rs->m);
    }
} ;

struct segtree {
    node *rt;

    void modify(node *p, int L, int R, int l, int r, int d) {
        if(L == l && R == r) {
            p->cover(d);
            return;
        }
        p->push();
        int m = L + R >> 1;
        if(r <= m)
            modify(p->ls, L, m, l, r, d);
        else if(l > m)
            modify(p->rs, m + 1, R, l, r, d);
        else modify(p->ls, L, m, l, m, d), modify(p->rs, m + 1, R, m + 1, r, d);
        p->upd();
    }

    int query(node *p, int L, int R, int dest) {
        if(!p) return 0;
        if(L == R) return p->m;
        p->push();
        int m = L + R >> 1;
        if(dest <= m) return query(p->ls, L, m, dest);
        else return query(p->rs, m + 1, R, dest);
    }

} T[2];

int main() {
    T[0].rt = new node();
    T[1].rt = new node();
    scanf("%d%d", &N, &Q);
    rep(i, 1, Q) {
        scanf("%d%d", &x, &y);
        swap(x, y);
        scanf("%s", dir);
        if(h[mp(x, y)]) {
            puts("0");
            continue;
        }
        h[mp(x, y)] = 1;
        if(dir[0] == 'U') {
            int fst = T[0].query(T[0].rt, 1, N, y); // max
            printf("%d\n", x - fst);
            T[1].modify(T[1].rt, 1, N, fst + 1, x, y);
        } else {
            int fst = T[1].query(T[1].rt, 1, N, x); // max
            printf("%d\n", y - fst);
            T[0].modify(T[0].rt, 1, N, fst + 1, y, x);
        }
    }
    return 0;
}

啊  - - 还有叉姐的set姿势 - - 模拟了一下觉得挺神奇的 - - 唉 - - 弱啊~

#include <cstdio>
#include <climits>
#include <set>

const int N = 200000 + 1;

typedef std::pair <int, int> Data;

int x[N], y[N], t[N];

int main()
{
    int n, q;
    scanf("%d%d", &n, &q);
    x[q] = y[q] = 0;
    std::set <Data> set;
    set.insert({0, q});
    set.insert({n + 1, q});
    for (int i = 0; i < q; ++ i) {
        char buffer[2];
        scanf("%d%d%s", x + i, y + i, buffer);
        t[i] = *buffer == 'U';
        std::set <Data>::iterator iterator;
        if (t[i]) {
            iterator = set.lower_bound({x[i], INT_MIN});
        } else {
            iterator = set.upper_bound({x[i], INT_MAX});
            iterator --;
        }
        if (x[i] == iterator->first) {
            puts("0");
        } else {
            int j = iterator->second;
            set.insert({x[i], i});
            if (t[i]) {
                printf("%d\n", y[i] - y[j]);
                y[i] = y[j];
            } else {
                printf("%d\n", x[i] - x[j]);
                x[i] = x[j];
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值