ARC 149 C

考虑将奇数放一边,偶数放一边:

  • 如果 \(2 \mid n\)
    image
    构造 \(c = (n-1)(n+1) = n^2 – 1\),于是对于每个奇数都可以有偶数对应。
  • 如果不是:
    image
    所以需要两个奇合数 \(c_1 = n^2\)\(c_2 = n^2 – 4\)(特判 \(n=3\)),而且红色相差 \(4\)。推个柿子就可以解决。

时间复杂度

显然为 \(\mathcal O(n^2)\)

点击查看代码
signed main() {
    int n = read();
    int a[1005][1005] = {};
    if (n % 2 == 0) {
        F(i, 1, n / 2 - 1) Fj 
            a[i][j] = 2 * (n * i + j) - 1;
        Fj a[n / 2][j] = 2 * j - 1;
        int c = n * n - 1;
        F(i, n / 2 + 1, n) Fj a[i][j] = c - a[n + 1 - i][j];
        a[n / 2 + 2][n] = n * n;
        Fi writes(a[i], n);
    } else if (n % 2 == 1)
        if (n == 3) {
            printf("%d %d %d \n"
                   "%d %d %d \n"
                   "%d %d %d \n"
                   , 5, 9, 1
                   , 3, 7, 8
                   , 6, 2, 4);
        } else {
            int c1 = n * n;
            int f = n / 2, c = n / 2 + 1;
            Fi 
                if (i <= c) a[c][i] = i * 2 - 1;
                else a[f][i] = i * 2 + 1;
            Fi 
                if (i <= c) a[c + 1][i] = c1 - a[c][i];
                else a[f + 1][i] = c1 - a[f][i];
            a[1][1] = c * 2 + 1;
            int ans = n * 2 + 1;
            F(i, 1, f) Fj if (!a[i][j]) 
                a[i][j] = (ans += 2);
            a[n][n] = n * n - a[1][1];
            ans = c1 - (2 * n + 1);
            F(i, c + 1, n) Fj if (!a[i][j])
                a[i][j] = (ans -= 2);
            Fi writes(a[i], n);
        }
}

ABC 268 F

对于两个字符串,定义

\[X(s) = \sum_{c \in s} [c = \texttt{“X”}] \]

\[\Sigma(s) = \sum_{c \in s} [c \ne \texttt{“X”}] \times c \]

,设初始排列 \(\pi = (1,2,\dots,n)\),对于一次修改 \(\pi’ = (1,2,\dots,i+1,i,n)\),得分增长了 \(\Sigma(s_{i+1})X(i) – \Sigma(s_i)X(i+1)\),颓一下柿子:
\(\Sigma(s_{i+1})X(i) – \Sigma(s_i)X(i+1) > 0 \iff\)
\(\Sigma(s_{i+1})X(i) > \Sigma(s_i)X(i+1) \iff\)
\(\dfrac{\Sigma(s_{i})}{X(i)} > \dfrac{\Sigma(s_{i+1})}{X(i+1)}\)
所以保证 \(\dfrac{\Sigma(s)}{X(s)} \uparrow\) 可以得到最佳结果。

时间复杂度

显然为 \(\mathcal O((\sum |s| + n) \log n)\)

点击查看代码
bool cmp(string s, string t) {
    int S = 0, SS = 0, x = 0, xx = 0;
    for (char c : s)
        if (c == 'X') x ++;
        else S += c - '0';
    for (char c : t)
        if (c == 'X') xx ++;
        else SS += c - '0';
    return (ld)(S)/x < (ld)(SS)/xx;
}
int main() {
    int n = read();
    string s[200005] = {};
    Fi cin >> s[i];
    sort(s + 1, s + n + 1, cmp);
    string awa = "";
    Fi awa += s[i];
    int got = 0;
    ll ans = 0;
    for (char c : awa)
        if (c == 'X') got ++;
        else ans += got * (c - '0');
    writeln(ans);
    return 0;
}

ABC 271 E

\(A_i \to B_i (L_i)\)
发现到一条 good path 一定可以 dp,因为如果真的存在一条 good path,那么这条边的起点一定可以用 good path 联通(也就是说,这条边的起点一定被 dp 到了)
状态转移方程:

\[f_{i,B_j} = \min(f_{i – 1,B_j}, f_{i – 1, A_j} + L_j) \]

,滚动数组优化即可。

时间复杂度

每条边最多访问一次,故时间复杂度为 \(\mathcal O(n + m + k)\)

ABC 272 E

显然有 \({\rm ans} \in [0, n]\),且影响答案的 因素\(\in [0, n]\)
所以考虑 \(i \in [a, b] \iff a_x + xi \in [0, n]\),对 \(\forall i \in [a, b]\) 枚举,并存进类似二维数组的结构当中,每次询问枚举答案即可

时间复杂度

\(|[a, b]| \le \lfloor \dfrac ni \rfloor + 1\)

\[\sum {\rm ans} \approx |二维数组| \le \sum\limits_{i=1}^n \lfloor \dfrac ni \rfloor + n = \sum\limits_{i=1}^n \lfloor \dfrac n{\lceil i \rceil} \rfloor + n = \int^{n}_{1} \lfloor \dfrac n{\lceil i \rceil} {\mathbf di} + n \rfloor \overset{\text{Lemma 1}}\le \int_1^n \dfrac ni {\mathbf di} + n = n \ln n + n \]

\(\text{Lemma 1}: \lfloor \dfrac n{\lceil i \rceil} \rfloor \le \dfrac ni\)
Proof: \(\lfloor \dfrac n{\lceil i \rceil} \rfloor \le \dfrac{n}{\lceil i \rceil} \le \dfrac ni\)

ABC 273 E

方法 \(1\)

发现是一个可持久化数组,用主席树维护即可。

时间复杂度

\(\mathcal O(q \log q)\) 加常数

较为方便的实现

Ext 模板库中提供了一种名为 \(\texttt{std::rope}\) 的容器,内部实现为可持久化平衡树,可以极为方便的解决本题。
使用 rope 小心野指针(map<int, rope*> 的未赋值部分是 nullptr

点击查看代码
using R = rope<int>*;
map<int, R> f;
int main() {
    int q = read(), L = 0;
    f[0] = new rope<int>;
    while (q --) {
        string s;
        cin >> s;
        if (s == "ADD") {
            int x = read();
            f[0]->push_back(x);
        } else if (s == "DELETE") {
            if (f[0]->size()) f[0]->erase(f[0]->size()-1, 1);
        } else if (s == "SAVE") {
            int x = read();
            f[x] = new rope<int>(*f[0]);
        } else {
            int x = read();
            if (f[x] == nullptr) f[x] = new rope<int>;
            f[0] = new rope<int>(*f[x]);
        }
        if (f[0]->size()) write((*f[0])[f[0]->size()-1]);
        else write(-1);
        putchar(' ');
    }
    return 0;
}

方法 \(2\)

进入正解。
本题的操作相当于维护树上的指针。
设当前的指针为 \(p\)

  1. \(\tt ADD\) 操作:为 \(p\) 添加一个子节点,其点权为 \(x\)
  2. \(\tt DELETE\) 操作:将 \(p\) 返到 \(p\) 的父亲那里。
  3. \(\tt SAVE\) 操作:记录 \(p\) 这个指针。
  4. \(\tt LOAD\) 操作:将 \(p\) 赋值为记录(若无此记录,赋值为根节点)

ARC 148 C

显然按两次按钮等价于不按。
于是函数 \(f : \mathscr P(n) \to \mathscr P(n)\),其中 \(f(S)\) 代表 \(\forall x \in S, 操作(x)\),是单射。考虑证明满射性:如果需要亮起灯 \(x\),则 \(T = \{x\} \cup son(x)\) 是一个满足条件的序列。于是有

\[f\left(\underset{s \in S}{\huge\bigtriangleup} \{s\} \cup {\rm Son}(s)\right) = S \]

,其中 \(\bigtriangleup\) 为对称差。
于是我们证明了 \(f\) 是双射。或者说,不存在输出 \(\tt -1\) 或非平凡的多组解。
考虑每个点都会在什么情况下被操作。操作 \(x,fa_x \iff\) 操作到 \(x\)。于是若 \(x\)\(fa_x\) 共同存在,则两个抵消,或 \(-2\),答案为:

\[|f^{-1}(S)| = \sum_{s \in S} (1 + |{\rm Son}(s)| – 2[{\rm fa}_s \in S]) \]

原文地址:http://www.cnblogs.com/lhx-oier/p/16760462.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性