Educational Codeforces Round 102 (Rated for Div. 2)

No More Inversions

给定\(k\),序列\(a\)长度为\(n\):\(1,2,3...k,k-1,k-2...k-(n-k)\),设序列\(a\)中逆序数为\(m\),给定排列\(p:1,2,3...k\),利用该排列形成新的序列\(b:b[i]= p[a[i]]\), 请你构造排列\(p\)使得序列\(b\)的逆序数不超过\(m\),且序列\(b\)字典序最大

题解:构造 + 思维 + 回文串的逆序对 : 记一下结论

引理:长度相同且元素不重复的回文串(\([s_1,s_2...s_k...s_2,s_1]\))逆序对恒定相等,其逆序数为\((k-1)^2\)

证明:

  1. 任选\(s_i,i<=k-1\),那么\(s_i...s_k...s_i\)三个之间一定会形成一个逆序对,那么这样的组合一共有\(k-1\)个,所以一定会产生\(k-1\)个逆序对

  2. 任选\(s_i,s_j且i,j<=k-1\),那么\(s_i...s_j...s_j...s_i\)四个之间一定会形成两个逆序对,那么这样的组合一共有\(C_{k-1}^{2}\)个,所以一定会产生\(2*C_{k-1}^{2}\)个逆序对

那么最终合并两种情况产生的逆序对,总共产生\((k-1)^2\)个逆序对

我们发现对于任意排列\(p\),假设\(p:[1,2,3,4]\),\(n=6\),那么序列\(b\)一定是\([1,2,3,4,3,2]\),也就是说\([k-(n-k),n]\)之间一定形成回文串,我们发现对于序列\(a\)而言,恰好也是在\([k-(n-k),n]\)之间形成回文串,根据引理得知两者之间逆序数相同,因为序列\(b\)的逆序数不能超过序列\(a\),所以对于序列\(b\)而言\([1,k-(n-k)-1]\)一定不能产生逆序对,也就是说前面一定为\(1,2,3...k-(n-k)-1\),那么如果想要使得字典序最大我们只要使得排列\(p\)在\([k-(n-k),k]\)中翻转即可,例如上述样例\(p:[1,4,3,2],b:[1,4,3,2,3,4]\)

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10; int n, k; void solve()
{
cin >> n >> k;
for (int i = 1; i <= (k - (n - k) - 1); ++i)
cout << i << " ";
for (int i = k; i >= (k - (n - k)); --i)
cout << i << " ";
cout << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}

Program

一共有\(n\)次操作,\(x\)初始值为\(0\),每次操作可以使\(x\)加1或减1,现在给出\(m\)次询问,每次询问给出\(l,r\),要求不执行\([l,r]\)之间的操作,让你给出如果只执行其他操作的话一共\(x\)会出现多少个不同的值

题解:前缀/后缀维护最值

我们思考如何得出答案:我们只要知道这些操作之中\(x\)的最大值和最小值就能知道出现多少个不同的值

我们只需要将每次操作看成-1或1,得到前缀和\(pre\),然后维护\(pre\)的前缀以及后缀最大值、最小值

对于询问\([l,r]\)来说,首先\([1,l-1]\)之间的最大值和最小值不会受到影响,但是\([r+1,n]\)之间的最大值和最小值会受到影响,实际上模拟后发现只需要在后缀最大值和最小值中减去\(pre[r]-pre[l-1]\)就能消除影响

本题也可以通过线段树维护区间最值求解,消除影响也是通过减去\(pre[r]-pre[l-1]\)

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10; int n, q;
int pre[N];
int pre_min[N], pre_max[N];
int suf_min[N], suf_max[N]; void solve()
{
cin >> n >> q;
string s;
cin >> s;
s = " " + s;
for (int i = 1; i <= n; ++i)
{
if (s[i] == '-')
pre[i] = pre[i - 1] - 1;
else
pre[i] = pre[i - 1] + 1;
pre_min[i] = min(pre_min[i - 1], pre[i]);
pre_max[i] = max(pre_max[i - 1], pre[i]);
}
suf_max[n + 1] = suf_min[n + 1] = pre[n];
for (int i = n; i >= 1; i--)
{
suf_min[i] = min(suf_min[i + 1], pre[i]);
suf_max[i] = max(suf_max[i + 1], pre[i]);
}
while (q--)
{
int l, r;
cin >> l >> r;
int sum = pre[r] - pre[l - 1];
int maxx = max(pre_max[l - 1], suf_max[r + 1] - sum);
int minn = min(pre_min[l - 1], suf_min[r + 1] - sum);
cout << maxx - minn + 1 << endl;
}
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}

Minimum Path

现给定有权无向图,\(n\)个点,\(m\)条边,定义两点之间路径的权值为:路径上所有边的权值之和\(-\)路径上的最大边权\(+\)路径上的最小边权;先让你求出原点\(1\)到其他每个节点路径的最小权值

题解:分层图最短路

因为要求的是路径最小权值,我们贪心的想删去最大权值边和加上最小权值边,我们将题目转化为删去任意一条边然后一条边加上两次,那么我们实现加减操作可以建立分层图:

  1. 建立四层图(将每个点拆成4个),每层正常建边
  2. 连接第一层到第二层的边权为\(0\),代表删去一条边
  3. 连接第二层到第四层(答案层)的边权为\(2*w\),代表一条边加上两次
  4. 但是第三层有什么用呢?实际上我们前面分层情况代表了先出现最大边后出现最小边,但是另一种情况就是先出现最小边再出现最大边,所以我们连接第一层到第三层的边权为\(2*w\),连接第三层到第四层(答案层)的边权为\(0\)
  5. 最后答案就在第四层,但是需要注意有些点和\(1\)直接相连,那么它既作为最大值也作为最小值,最后路径权值就等于路径上边权之和,所以我们需要特判一下\(min(dis[i],dis[i+3*n])\)

建完图后跑一遍\(dij\)即可

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10; int n, m;
vector<pii> g[N << 2];
int dis[N << 2];
int vis[N << 2]; void dij(int st)
{
for (int i = 1; i <= 4 * n; ++i)
dis[i] = INF;
dis[st] = 0;
priority_queue<pii, vector<pii>, greater<pii>> q;
q.push({dis[st], st});
while (q.size())
{
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = 1;
for (auto [v, w] : g[u])
{
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
} void solve()
{
cin >> n >> m;
for (int i = 1, u, v, w; i <= m; ++i)
{
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
g[u + n].push_back({v + n, w});
g[v + n].push_back({u + n, w});
g[u + 2 * n].push_back({v + 2 * n, w});
g[v + 2 * n].push_back({u + 2 * n, w});
g[u + 3 * n].push_back({v + 3 * n, w});
g[v + 3 * n].push_back({u + 3 * n, w});
g[u].push_back({v + n, 0});
g[v].push_back({u + n, 0});
g[u].push_back({v + 2 * n, 2 * w});
g[v].push_back({u + 2 * n, 2 * w});
g[u + n].push_back({v + 3 * n, 2 * w});
g[v + n].push_back({u + 3 * n, 2 * w});
g[u + 2 * n].push_back({v + 3 * n, 0});
g[v + 2 * n].push_back({u + 3 * n, 0});
}
dij(1);
for (int i = 2; i <= n; ++i)
cout << min(dis[i], dis[i + 3 * n]) << " ";
cout << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}

Educational Codeforces Round 102 (Rated for Div的更多相关文章

  1. Educational Codeforces Round 102 (Rated for Div. 2)

    比赛地址 A(水题) 题目链接 题目: 给出一个数组\(a\)并能进行一个操作使得数组元素更改为数组任意其他两元素之和,问是否可以让数组元素全部小于等于\(d\) 解析: 排序后判断最大值是否小于等于 ...

  2. Educational Codeforces Round 102 (Rated for Div. 2) D. Program (思维,前缀和)

    题意:给你一个只含\(+\)和\(-\)的字符串,给你一个数\(x\),\(x\)初始为\(0\),随着字符串的遍历会加一减一,现在有\(m\)个询问,每个询问给出一个区间\([l,r]\)表示将这个 ...

  3. Educational Codeforces Round 102 (Rated for Div. 2) B. String LCM (构造,思维)

    题意:给你两个字符串\(a\)和\(b\),找出它们的\(lcm\),即构造一个新的字符串\(c\),使得\(c\)可以由\(x\)个\(a\)得到,并且可以由\(y\)个\(b\)得到,输出\(c\ ...

  4. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  5. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  6. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  7. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  8. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  9. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  10. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

随机推荐

  1. Unocss使用

    目录: 安装 简单使用 自定义规则 安装 { "dependencies": { "unocss": "^0.55.6", "vu ...

  2. 利用PaddleHub 进行人脸检测识别、并对图片进行抠图

    利用PaddleHub 进行人脸检测识别.并对图片进行抠图   本文是利用百度的飞桨平台的paddle进行人脸的检测和抠图,但是里面也有一些小问题,特记录一下笔记,以便以后观看学习. 环境:pytho ...

  3. Hugging Face NLP课程学习记录 - 2. 使用 Hugging Face Transformers

    Hugging Face NLP课程学习记录 - 2. 使用 Hugging Face Transformers 说明: 首次发表日期:2024-09-19 官网: https://huggingfa ...

  4. 倒计时 3 天!10.23 相约杭州,云原生 Meetup 等你来!

    云原生技术交流 Meetup 杭州站开启,快来报名吧! 活动简介 随着云原生技术的普及,整个市场已经变成了节奏非常快的软件驱动型市场,使用云原生技术栈来迭代发布应用已经成为常态,但是如何更好的应用云原 ...

  5. Pandas 空值数据的索引 位置 行号

    前言 先说一下什么是pandas, 这个东西其实就是一个处理表格数据的一个库.可以把它看做是一个没有图形化界面的Excel. Pandas中的空值是非常多的,这体现了数据搜集的一个不可避免的方面.由于 ...

  6. 《使用Gin框架构建分布式应用》阅读笔记:p127-p142

    <用Gin框架构建分布式应用>学习第9天,p127-p142总结,总计16页. 一.技术总结 1.Authentication方式汇总 (1)API keys API keys 认证方式示 ...

  7. Angular 19 "要" 来了⚡

    前言 Angular 19 预计会在 11 月中旬发布,目前 (2024-10-27) 最新版本是 v19.0.0-next.11. 这次 v19 的改动可不小哦,新增了很多功能,甚至连 effect ...

  8. 了解 Uniswap V2(DEX)

    Uniswap V2 是一个基于以太坊的去中心化交易所(DEX),它通过流动性池和自动化做市商(AMM)模型来实现去中心化的代币交换.以下是 Uniswap V2 的核心概念: 1. 自动化做市商(A ...

  9. Next.js 从零入门到实战 3:2024最新完整教程 | 包含SSR、API路由和性能优化

    CSS样式学习 上一篇文章讲到如何创建一个脚手架程序,目前我们已经有了一个nextjs的基本框架,因此我们可以在这个基础上进行改造.打开我们项目中的page.tsx页面,这里是程序的主页面,也就是我们 ...

  10. 在嵌入式设备中实现webrtc的第三种方式②

    先贴上效果图以及操作路径. 操作路径为:启动信令服务器,配置浏览器关闭mDNS,双端登录,浏览器端邀请.最终连接成功建立,我们通过datachannel成功通信 (关闭mDNS是因为谷歌浏览器隐藏了局 ...