D - Bicolored RBS

给定一个括号序列,现在你必须对每一个括号涂成蓝色或红色,要求使得涂完后的红色括号和蓝色括号序列都必须是合法的括号序列,设红色括号形成的的括号序列的深度为\(dep_1\),蓝色括号形成的括号序列的深度为\(dep_2\),答案为\(max(dep_1,dep_2)\),现在让你求出答案的最小值,即将答案最小化

题解:贪心

  • 引理:括号序列的深度\(dep\)即为其所有位置上左括号的前缀数量减去右括号前缀数量的最大值,或者说是我们将括号序列放入栈中时的最大深度

那么实际上我们对于给定的括号序列,在未涂色前我们可以将其深度\(dep\)求出,那么我们只要试着将该深度平分给红色括号序列和蓝色括号序列即可:

  1. 如果\(dep\)是偶数,那么\(dep_1=dep/2,dep_2=dep/2\)
  2. 如果\(dep\)是奇数,那么\(dep_1=dep/2+1,dep_2=dep/2\)或者\(dep_1=dep/2,dep_2=dep/2+1\)

那么实际上我们发现我们只要维护两个栈(一个栈代表红色括号序列,一个栈代表蓝色括号序列)

  1. 如果当前入栈的元素是左括号,我们只要看哪一个栈的深度小我们就放哪一个栈
  2. 如果当前入栈的元素时右括号,我们只要看哪一个栈的深度大我们就放哪一个栈

这样就能贪心的使得两个栈深度的最大值最小化

#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\)是合法的右端点,所以我们可以利用双指针解决该问题

那么我们在利用双指针处理时需要预处理以下几个问题:

  1. 对于\(f(l,r)\)来说,位于区间\([1,l-1]\)和\([r+1,m]\)中的所有元素在序列中一定是单调不递减,也就是说位于区间\([1,l-1]\)和\([r+1,m]\)中的所有元素之间不会形成逆序对,所以我们需要预处理出所有合法的左端点\(l\),使得在区间\([1,l]\)中不存在逆序对,同时预处理出所有合法的右端点\(r\),使得\([r,m]\)中不会存在逆序对

  2. 我们首先需要预处理出所有合法的左端点\(l\),即属于\([1,l]\)的元素形成的序列不会形成逆序对,同时我们发现所有合法的左端点\(l\)一定是连续的,也就说合法的左端点是一段区间\([1,ql]\),在这个区间中所有的点都是合法的左端点,那么我们的左指针\(i\)就可以在这段区间中移动,但是现在的关键是我们怎么预处理出这段合法的区间?

  3. 首先我们一定能够预处理出所有元素在序列中出现的最左边的位置\(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])\)

  4. 那么类似左端点,我们同样可以预处理所有合法的右端点区间\([qr,m]\),右指针\(j\)可以在这段区间中移动,不再赘述

  5. 那么对于\(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的更多相关文章

  1. Educational Codeforces Round 65 (Rated for Div. 2)题解

    Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...

  2. 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 ...

  3. 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 ...

  4. 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 ...

  5. 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  ...

  6. 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 ...

  7. [ 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 ...

  8. Educational Codeforces Round 65 (Rated for Div. 2)

    A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 ...

  9. Educational Codeforces Round 65 (Rated for Div. 2) E. Range Deleting(思维+coding)

    传送门 参考资料: [1]:https://blog.csdn.net/weixin_43262291/article/details/90271693 题意: 给你一个包含 n 个数的序列 a,并且 ...

  10. 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  ...

随机推荐

  1. 八,SpringBoot Web 开发访问静态资源(附+详细源码剖析)

    八,SpringBoot Web 开发访问静态资源(附+详细源码剖析) @ 目录 八,SpringBoot Web 开发访问静态资源(附+详细源码剖析) 1. 基本介绍 2. 快速入门 2.1 准备工 ...

  2. DOM – IntersectionObserver

    介绍 IntersectionObserver 的作用是监听某个元素是否出现在框内 (比如 viewport). 它可以实现 lazy load image, 一开始图片是没有加载的, 当图片出现在 ...

  3. Figma 学习笔记 – Frame

    Frame = <div> Frame 就类似 HTML 中的 div, 它和形状 rectangle 特性上蛮相识的, 但是使用场景其实差很多, 所以不要搞错哦. (除了图片很少会用到 ...

  4. Python写入数据到MySQL数据库并读取

    1.导入pymysql库   命令行输入pip3 install PyMySQL    2.连接数据库 import pymysql db = pymysql.connect(host='localh ...

  5. 三大硬核方式揭秘:Java如何与底层硬件和工业设备轻松通信!

    大家好,我是V哥,程序员聊天真是三句不到离不开技术啊,这不前两天跟一个哥们吃饭,他是我好多年前的学员了,一直保持着联系,现在都李总了,在做工业互联网相关的项目,真是只要 Java 学得好,能干一辈子, ...

  6. 【赵渝强老师】Kafka的体系架构

    一.什么是Kafka? 数据工程中最具挑战性的部分之一是如何从不同点收集和传输大量数据到分布式系统进行处理和分析.需要通过消息队列正确地分离大量数据,因为如果一部分数据无法传送,则可以在系统恢复时传输 ...

  7. Excel读写之xlrd模块

    1.1.xlrd模块介绍 xlrd:用于读取Excle数据文件将返回的数据对象放到内存中,然后查询数据文件对象的相关信息. xlwt:用于在内存中生成新的数据文件对象,处理完成后写入到Excel数据文 ...

  8. docker-compose -- 创建 redis && mysql

    version: '3' services: nest-admin-web: image: buqiyuan/vue3-antdv-admin:stable container_name: nest- ...

  9. Math 数学库

    Math.random()  随机数字 Math.PI  圆周率

  10. KubeKey v3.1 发布:快速自定义离线安装包

    日前,KubeKey v3.1 正式发布.该版本主要对离线场景部署.离线包制作以及向 Kubernetes v1.24+ 升级进行了优化. KubeKey 简介 KubeKey 是 KubeSpher ...