ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

cf1234 E. Special Permutations

2022-04-18 13:00:07  阅读:158  来源: 互联网

标签:val int Permutations 差分 cf1234 cdots signed 数组 Special


题意:

有一个 \(1\sim n\) 的从小到大的排列,即 \(1,2,\cdots ,n\),记为 \(P_1\)

定义 \(P_i\) 为:在 \(P_1\) 中把数字 \(i\) 移到最前面,其他数字的相对位置不变得到的新排列

定义 \(p_x(P_i)\) 为数字 \(x\) 在排列 \(P_i\) 中的位置

给定数组 \(a[]\),定义函数 \(f_i\) 为 \(\Sigma |p_{a_k}(P_i)-p_{a_k}(P_i)|\)

输出 \(f_1,f_2,\cdots ,f_n\)

思路:

法一:

考虑从 \(P_x\) 到 \(P_{x+1}\) 有什么变化,实际上只有 \(p_x\) 从 \(1\) 变成 \(x+1\),同时 \(p_{x+1}\) 从 \(x+1\) 变成 \(1\),其他都不变。所以可以每次修改被影响的位置,求出所有 \(f\)

实现起来感觉很丑,不写了。下面的方法比较优雅

法二:差分

把要求的 \(f[]\) 写成差分数组,初始所有 \(f_i=0\)

考虑一对在 \(a[]\) 中相邻的数 \(x=a_k,y=a_{k+1}\),不妨设 \(x<y\)。那么 \(x,y\) 对某个 \(f_i\) 的贡献是多少呢?

  1. 若 \(i<x\),则 \(p_x=x,p_y=y\),对 \(f_i\) 的贡献就是 \(y-x\),即 \(f_i+=y-x\)

  2. 若 \(i=x\),则 \(p_x=1,p_y=y\),那么 \(f_i+=y-1\)

  3. 若 \(x<i<y\),则 \(p_x=x+1,p_y=y\),那么 \(f_i+=y-x-1\)

  4. 若 \(i=y\),则 \(p_x=x+1,p_y=1\),那么 \(f_i+=x\)

  5. 若 \(i>y\),则 \(p_x=x+1,p_y=y+1\),那么 \(f_i+=y-x\)

也就是说,\(x,y\) 会让 \(f_x\) 加上 \(y-1\),同时让 \(f_y\) 加上 \(x\),让 \(f_{(x,y)}\) 加上 \(y-x-1\),让 \(f_{[1,x)}\) 和 \(f_{(y,n]}\) 加上 \(y-x\)

用差分数组实现上述区间加操作,最后求一下前缀和得到原数组

const signed N = 2e5 + 3;
int n, m, a[N]; ll f[N];

void add(int l, int r, int val) {
    f[l] += val, f[r+1] -= val;
}

signed main() {
    iofast;
    cin >> n >> m;
    for(int i = 1; i <= m; i++) cin >> a[i];

    for(int i = 1; i < m; i++) {
        int x = a[i], y = a[i+1];
        if(x == y) continue;
        if(x > y) swap(x, y); //保证x<y
        add(1, x - 1, y - x);
        add(x, x, y - 1);
        add(x + 1, y - 1, y - x - 1);
        add(y, y, x);
        add(y + 1, n, y - x);
    }

    for(int i = 1; i <= n; i++) //前缀和
        cout << (f[i] += f[i-1]) << ' ';
}

标签:val,int,Permutations,差分,cf1234,cdots,signed,数组,Special
来源: https://www.cnblogs.com/wushansinger/p/16159151.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有