Educational Codeforces Round 65 (Rated for Div
D - Bicolored RBS
给定一个括号序列,现在你必须对每一个括号涂成蓝色或红色,要求使得涂完后的红色括号和蓝色括号序列都必须是合法的括号序列,设红色括号形成的的括号序列的深度为\(dep_1\),蓝色括号形成的括号序列的深度为\(dep_2\),答案为\(max(dep_1,dep_2)\),现在让你求出答案的最小值,即将答案最小化
题解:贪心
- 引理:括号序列的深度\(dep\)即为其所有位置上左括号的前缀数量减去右括号前缀数量的最大值,或者说是我们将括号序列放入栈中时的最大深度
那么实际上我们对于给定的括号序列,在未涂色前我们可以将其深度\(dep\)求出,那么我们只要试着将该深度平分给红色括号序列和蓝色括号序列即可:
- 如果\(dep\)是偶数,那么\(dep_1=dep/2,dep_2=dep/2\)
- 如果\(dep\)是奇数,那么\(dep_1=dep/2+1,dep_2=dep/2\)或者\(dep_1=dep/2,dep_2=dep/2+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;
int stk1[N], stk2[N], tt1, tt2;
void solve()
{
cin >> n;
string s;
cin >> s;
s = " " + s;
string ans = s;
for (int i = 1; i <= n; ++i)
{
if (s[i] == '(')
{
if (tt1 <= tt2)
{
stk1[++tt1] = i;
ans[i] = '0';
}
else
{
stk2[++tt2] = i;
ans[i] = '1';
}
}
else
{
if (tt1 <= tt2 && tt2)
{
tt2--;
ans[i] = '1';
}
else if (tt1 > tt2 && tt1)
{
tt1--;
ans[i] = '0';
}
}
}
for (int i = 1; i <= n; ++i)
cout << ans[i];
cout << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}
E - Range Deleting
给定长度为\(n\)的数组\(a\),其中\(a_i<=m,(1<=n,m<=1e6)\),定义\(f(l,r)\)为删除数组\(a\)中数值在\([l,r]\)范围内的元素后剩余的数组\((1<=l<=r<=m)\),请你求出\(f(l,r)\)是单调不递减序列的数量
题解:双指针 : 好题目
首先我们可以发现:
如果\(f(l,r)\)是合法的单调不递减序列,那么对于\(1<=l'<l,r<r'<=m\),\(f(l',r')\)一定也是合法的单调不递减序列,那么说明随着左端点\(l\)变化,右端点\(r\)的变化具有单调性,即对于一个合法的左端点\(l\)我们在求出其右边第一个合法的右端点\(r\)(对于\(l\)来说是合法的),那么对于所有\([r,m]\)的右端点都是合法的右端点,那么我们再向右找到该合法左端点的下一个合法左端点\(l'\),显然根据我们上面的分析一定存在\(r'>=r\)是合法的右端点,所以我们可以利用双指针解决该问题
那么我们在利用双指针处理时需要预处理以下几个问题:
对于\(f(l,r)\)来说,位于区间\([1,l-1]\)和\([r+1,m]\)中的所有元素在序列中一定是单调不递减,也就是说位于区间\([1,l-1]\)和\([r+1,m]\)中的所有元素之间不会形成逆序对,所以我们需要预处理出所有合法的左端点\(l\),使得在区间\([1,l]\)中不存在逆序对,同时预处理出所有合法的右端点\(r\),使得\([r,m]\)中不会存在逆序对
我们首先需要预处理出所有合法的左端点\(l\),即属于\([1,l]\)的元素形成的序列不会形成逆序对,同时我们发现所有合法的左端点\(l\)一定是连续的,也就说合法的左端点是一段区间\([1,ql]\),在这个区间中所有的点都是合法的左端点,那么我们的左指针\(i\)就可以在这段区间中移动,但是现在的关键是我们怎么预处理出这段合法的区间?
首先我们一定能够预处理出所有元素在序列中出现的最左边的位置\(posl\)和最右边的位置\(posr\),现在我们假设区间\([1,l]\)是合法的,也就是说该区间中的元素不存在逆序对,那么对于区间\([1,l+1]\)来说我们只要判断值为\(l+1\)的元素在序列中出现的最左边的位置会不会比区间\([1,l]\)中所有元素在序列中出现的位置中的最大位置来的小,如果小于说明区间\([1,l+1]\)中存在逆序对,反之说明\([1,l+1]\)同样合法,那么我们现在又需要多知道一个东西:元素值位于区间\([1,i]\)中的所有元素所处的最右边位置,那么对于这个我们只需要利用\(dp\)进行转移即可:\(R[i]=max(R[i-1],posr[i])\)
那么类似左端点,我们同样可以预处理所有合法的右端点区间\([qr,m]\),右指针\(j\)可以在这段区间中移动,不再赘述
那么对于\(i∈[1,ql],r∈[qr,m]\),我们如何去检查\(f(i,j)\)是合法的呢?显然我们只要判断区间\([1,i-1]\)的最右边位置是否和区间\([j+1,m]\)中最左边的位置形成逆序对即可
#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 = 1e6 + 10, M = 4e5 + 10;
int n, m;
int a[N];
int posl[N], posr[N], L[N], R[N];
void solve()
{
cin >> n >> m;
for (int i = 0; i <= m + 1; ++i)
{
posl[i] = INF;
posr[i] = -INF;
L[i] = INF;
R[i] = -INF;
}
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = 1; i <= n; ++i)
{
posl[a[i]] = min(posl[a[i]], i);
posr[a[i]] = max(posr[a[i]], i);
}
for (int i = 1; i <= m; ++i)
R[i] = max(R[i - 1], posr[i]); //dp预处理[1,i]中最右边元素位置
for (int i = m; i >= 1; i--)
L[i] = min(L[i + 1], posl[i]); //dp预处理[i,m]中最左边元素位置
int ql = 1, qr = m;
while (posl[ql] >= R[ql - 1] && ql <= m)
ql++; //找到合法左端点区间[1,ql)
while (posr[qr] <= L[qr + 1] && qr >= 1)
qr--; //找到合法右端点区间(qr,m],开区间的原因在双指针中体现
int ans = 0;
for (int i = 1, j = qr; i <= ql; ++i)
{
while (j <= m && (j < i || R[i - 1] > L[j + 1]))
j++;
ans += m - j + 1;
}
cout << ans << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}
Educational Codeforces Round 65 (Rated for Div的更多相关文章
- Educational Codeforces Round 65 (Rated for Div. 2)题解
Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...
- Educational Codeforces Round 65 (Rated for Div. 2) D. Bicolored RBS
链接:https://codeforces.com/contest/1167/problem/D 题意: A string is called bracket sequence if it does ...
- Educational Codeforces Round 65 (Rated for Div. 2) C. News Distribution
链接:https://codeforces.com/contest/1167/problem/C 题意: In some social network, there are nn users comm ...
- Educational Codeforces Round 65 (Rated for Div. 2) B. Lost Numbers
链接:https://codeforces.com/contest/1167/problem/B 题意: This is an interactive problem. Remember to flu ...
- Educational Codeforces Round 65 (Rated for Div. 2) A. Telephone Number
链接:https://codeforces.com/contest/1167/problem/A 题意: A telephone number is a sequence of exactly 11 ...
- Educational Codeforces Round 65 (Rated for Div. 2)B. Lost Numbers(交互)
This is an interactive problem. Remember to flush your output while communicating with the testing p ...
- [ Educational Codeforces Round 65 (Rated for Div. 2)][二分]
https://codeforc.es/contest/1167/problem/E E. Range Deleting time limit per test 2 seconds memory li ...
- Educational Codeforces Round 65 (Rated for Div. 2)
A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 ...
- Educational Codeforces Round 65 (Rated for Div. 2) E. Range Deleting(思维+coding)
传送门 参考资料: [1]:https://blog.csdn.net/weixin_43262291/article/details/90271693 题意: 给你一个包含 n 个数的序列 a,并且 ...
- Educational Codeforces Round 65 (Rated for Div. 2)(ACD)B是交互题,不怎么会
A. Telephone Number A telephone number is a sequence of exactly 11 digits, where the first digit is ...
随机推荐
- Qml 实现水波进度动画条
[写在前面] 最近看到一个非常有趣的动画效果:水波进度动画. 学习了一下实现思路,觉得很有意思. 不过原版是 HTML + CSS,我这里用的是 Qml,有一些小技巧,分享给大家~ [正文开始] 老样 ...
- Java Pom两个模块需要互相引用怎么办
1. Java POM模块化是什么 在Java项目中,特别是在使用Maven作为构建工具时,"POM模块化"是一个重要的概念,它指的是将大型项目拆分成多个更小.更易于管理的模块(或 ...
- iframe嵌套登录页-页面无法加载
背景 活动页面和登录页跨域,过去都是跳转到登录页登录之后再跳转回来,体验不好. 现在需要将登录模块嵌入到活动页,因为懒,不想开发重复的模块,首先我想到的是iframe 刚开始还能正常使用,一段时间后安 ...
- Python计算傅里叶变换
技术背景 傅里叶变换在几乎所有计算相关领域都有可能被使用到,例如通信领域的滤波.材料领域的晶格倒易空间计算还有分子动力学中的倒易力场能量项等等.最简单的例子来说,计算周期性盒子的电势能\(k\sum_ ...
- 暑假集训CSP提高模拟 16
\[暑假集训CSP提高模拟 \lim_{x\rightarrow\infty}\frac{8f_{x}}{f_{x+1}}\times(\sqrt{5}+1),\ \forall f_{x}=f_{x ...
- STL标准模板库
STL(Standard Template Library)标准模板库 是C++标准库中的一个重要组成部分,它提供了一组通用的模板类和函数,用于数据结构和算法的实现.STL的核心部分包括容器.算法和迭 ...
- 主要将子文件下大量图片进行路径编号,并保存到csv文件当中。方便直接从文件读取图片路径以及其他图片信息
# coding: utf-8 #主要将子文件下大量图片进行路径编号,并保存到csv文件当中.方便直接从文件读取图片路径以及其他图片信息. #我做的是图像分割,所以存在三类分割区域:["la ...
- 74.数组map能干什么,会改变原数组吗
map是处理数据的方法,不会改变原数组,会返回一个新数组 : filter 也不会改变原数组,会返回新数组 : forEach 也不会改变原数组,不会返回新数组 : reduce不会改变原数组 : 是 ...
- 【Treatment-Rec 论文阅读】Data-driven Automatic Treatment Regimen Development and Recommendation
Data-driven Automatic Treatment Regimen Development and Recommendation Authors: Leilei Sun, Chuanren ...
- Android复习(二)应用资源——>更多类型
更多资源类型 本页面定义了更多类型的可具体化的资源,包括: Bool 带有布尔值的 XML 资源. 颜色 带有颜色值(十六进制颜色)的 XML 资源. 尺寸 带有尺寸值(包含度量单位)的 XML 资源 ...