• Codeforces Raif Round 1 (Div. 1 + Div. 2)


    A

    #include <bits/stdc++.h>
    #define all(n) (n).begin(), (n).end()
    #define se second
    #define fi first
    #define pb push_back
    #define mp make_pair
    #define sqr(n) (n)*(n)
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i=(a);i>=(b);--i)
    #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> PII;
    typedef pair<ll, ll> PLL;
    typedef vector<int> VI;
    typedef double db;
     
    template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
    template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
    template<class T> void clear(T& a) { T().swap(a); }
     
    const int N = 2e5 + 5;
     
    int n, m, _, k;
    ll a[N], b[N];
     
    int main() {
        IOS;
        for (cin >> _; _; --_) {
            ll a, b, x, y; cin >> a >> b >> x >> y;
            ll ans = abs(x - a) + abs(y - b) + 2;
            if (x == a || y == b) ans -= 2;
            cout << ans << '
    '; 
        } 
        return 0;
    }
    

    B

    char s[N];
     
    int main() {
        IOS;
        for (cin >> _; _; --_) {
            cin >> n >> s + 1;
            int a = 0;
            unordered_set<int> st;
            rep (i, 1, n) {
                if (s[i] == '-') st.insert(i % n), st.insert((i + 1) % n);
                else if (s[i] == '>') {
                    if (a == 0) a = 1;
                    else if (a == 2) a = -1;
                } else {
                    if (a == 0) a = 2;
                    else if (a == 1) a = -1;
                }
            }
            if (a != -1) cout << n << '
    ';
            else cout << st.size() << '
    ';
        }
        return 0;
    }
    

    C

    贪心模拟

    int main() {
        IOS;
        for (cin >> _; _; --_) {
            string s; cin >> s;
            int x = 0, y = 0, ans = 0;
            bool f = 0;
            for (auto c : s) {
                if (c == 'A') {
                    if (f && y) ++x, y = 0, f = 0;
                    ++x;
                }
                else if (c == 'B') {
                    if (x) --x, ++ans, f = 1;
                    else {
                        ++y;
                        if (y == 2) ++ans, y = 0;
                    }
                }
            }
            cout << s.size() - (ans << 1) << '
    ';
        } 
        return 0;
    }
    

    D

    考虑到后效性, 倒着放, 同时对于行, 也是从 n 到 1, 把后效性消掉

    我用的set只是为了图形优美, 什么容器都可

    int a[N];
    VI ans[N];
    set<PII> st;
    set<int> t;
     
    int main() {
        IOS; cin >> n; int res = 0; m = n;
        rep(i, 1, n) cin >> a[i];
        bool f = 1;
        per(i, n, 1) {
            if (a[i] == 0) continue;
            if (a[i] == 1) ans[i].pb(m), ++res, st.insert({ m--, i });
            else if (a[i] == 2) {
                if (st.empty()) { f = 0; break; }
                PII ls = *st.rbegin();
                ans[i].pb(ls.fi); ++res;
                st.erase(ls); t.insert(i);
            }
            else {
                if (st.empty() && t.empty()) { f = 0; break; }
                if (!t.empty()) {
                    int ls = *t.begin();
                    ans[i].pb(m); ++res;
                    ans[ls].pb(m--); ++res;
                    t.erase(ls); t.insert(i);
                }
                else {
                    PII ls = *st.rbegin();
                    ans[i].pb(m); ++res;
                    ans[ls.se].pb(m--); ++res;
                    st.erase(ls); t.insert(i);
                }
            }
        }
        if (!f || m < 0 || res > 2 * n) { cout << -1; return 0; }
        cout << res << '
    ';
        rep(i, 1, n) for (auto j : ans[i]) cout << j - k << ' ' << i << '
    ';
        return 0;
    }
    

    E

    优先队列

    注意到, 将一个胡萝卜分的快数越多, 花费的时间越少, 就发现是优先队列, 每次选取 多分出一块 省的时间最多的那一根胡萝卜就行

    ll a[N], b[N];
    
    ll get(int x, int k) {
    	if (a[x] < k) return 1e9;
    	ll siz = a[x] / k, res = a[x] % k;
    	return sqr(siz + 1) * res + sqr(siz) * (k - res);  
    }
    
    int main() {
        IOS; cin >> n >> k;
    	priority_queue<PLI> q;
    	rep (i, 1, n) {
    		cin >> a[i], b[i] = 1;
    		q.push({ get(i, 1) - get(i, 2), i });
    	}
    	rep (i, n + 1, k) {
    		int x = q.top().se; q.pop();
    		++b[x]; q.push({ get(x, b[x]) - get(x, b[x] + 1), x });
    	}
    	ll ans = 0;
    	rep (i, 1, n) ans += get(i, b[i]);
    	cout << ans;
        return 0;
    }
    

    F

    //下标从1开始

    dp(线段树也可), 常数大的O(n)

    g[i] 表示 j~i (1 <= j <= i) 对答案的贡献, 那么最后的答案就是 (sum g[i])

    明显 s[i] == '0', g[i] == g[i - 1],

    对于 s[i] == '1', 讨论要复杂一些

    因为是考虑区间最长的 '1', 理所应当我们要存个 t[i], 表示以 i 结尾的最长 '1', 毕竟在遍历 i 的时候, 区间最长 '1' 是会变的

    显然 if s[i] == '0', t[i] = 0; else t[i] = t[i-1] + 1

    当从 i - 1 到 i 的时候最后一段 '1' 变长了(s[i] == '1') 也就是说, 在上一段最后 t[i]个字符 到 (i - 1) - t[i - 1] 原本最长段是 t[i - 1](t[i - 1] == t[i] - 1)

    然而现在成了 t[i], 也就说在这个区间内 多贡献了个区间长度, 对于 i-t[i]~i 也是多贡献了个区间长度

    设 f[i] 表示 上一个长度为 i 的 '1' 串的起始位置, "1101" 在对于第4个位置的时候, 当前 '1' 段为 [4,4], 那么上一个 长度为 1 的段 是 [2, 2], 长度为2的段时[1, 2], 故 f[1] = 2, f[2] = 2

    那么 s[i] == '1' 转移就已经出来了 g[i] = g[i + 1] + (i - t[i] - f[t[i]]) + t[i];

    那么现在的问题成了怎么求 f[i], 显然 f[i] 对于 '1' 段是倒着的, "111110", 对于6位置 f[1] = 5, f[2] = 2, f[3] = 3, f[4] = 4, f[5] = 5;

    其实已经发现了 f[i] = 上一个串的长度 - 正着数的位置, 比如对于 位置 i,

    f[length(包含i的最长 '1' 的长度) - t[i] + 1] = i

    至于长度嘛, 预处理O(n), 就行了, 虽然我用的并查集, 但还是O(1)的合并, 直接和 '1' 段的起始坐标最为祖先

    然后我们又发现个问题, f[i] 随着 i 更新, 但我们计算 g[i] 的时候是想要未更新之前的 f[i], 如果先转移完, 在取跟新 f[i], 那必定超时(每遇到一个 '1' 串, 你都要重新遍历一遍)

    所以每个位置存两个 f[i] 就好了, 当前的和上一个的, 通过下标判断, 应该取哪个和更新哪个

    这样 f[i] 我们也有了

    总的复杂度 O(n), 常数可能有点大, 并查集这里直接是O(1)

    #include <bits/stdc++.h>
    #define all(n) (n).begin(), (n).end()
    #define se second
    #define fi first
    #define pb push_back
    #define mp make_pair
    #define sqr(n) (n)*(n)
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i=(a);i>=(b);--i)
    #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> PII;
    typedef pair<ll, ll> PLL;
    typedef pair<ll, int> PLI;
    typedef vector<int> VI;
    typedef double db;
    
    template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
    template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
    template<class T> void clear(T& a) { T().swap(a); }
    
    const int N = 5e5 + 5;
    
    int n, m, _, k;
    int fa[N], siz[N];
    ll g[N], t[N];
    PII f[N];
    char s[N];
    
    int find(int x) {
    	return x == fa[x] ? x : fa[x] = find(fa[x]);
    }
    
    void unit(int x, int y) {
    	x = find(x); fa[y] = x; siz[x] += siz[y];
    }
    
    int get(int x, int k) {
    	if (f[k] == PII{ 0, 0 }) return 0;
    	if (f[k].se > f[k].fi) swap(f[k].fi, f[k].se);
    	if (fa[f[k].fi] != fa[x]) return f[k].fi;
    	return f[k].se;
    }
    
    void change(int x, int k) {
    	if (f[k].fi == 0) f[k].fi = x;
    	else if (f[k].se == 0) f[k].se = x;
    	else if (f[k].fi > f[k].se) f[k].se = x;
    	else f[k].fi = x;
    }
    
    int main() {
    	IOS; cin >> n >> s + 1;
    	rep(i, 1, n) fa[i] = i;
    	rep(i, 1, n)
    		if (s[i] == '1') {
    			t[i] = t[i - 1] + 1; siz[i] = 1;
    			if (s[i - 1] == '1') unit(i - 1, i);
    		}
    
    	rep(i, 1, n) {
    		if (s[i] == '0') g[i] = g[i - 1];
    		else {
    			g[i] = g[i - 1] + i - t[i] - get(i, t[i]) + t[i];
    			int a = siz[find(i)]; change(i, a - t[i] + 1);
    		}
    	}
    	ll ans = 0;
    	rep(i, 1, n) ans += g[i];
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    SWFUpload说明文档
    Ubuntu中root用户和user用户的相互切换
    不用IF比较两数大小
    Linux服务器下验证码图片不显示问题
    常用CSS语法
    常用CSS语法
    漫谈DataList的用法
    Session丢失浅析
    浅谈C#托管程序中的资源释放问题
    C#2.0 泛型详解
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/13834474.html
Copyright © 2020-2023  润新知