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. Angular Material 18+ 高级教程 – CDK Overlay

    Overlay, Dialog, Modal, Popover 傻傻分不清楚 参考: Medium – Modal?Dialog?你真的知道他們是什麼嗎? Popups, dialogs, toolt ...

  2. 墨天轮最受DBA欢迎的数据库技术文档-故障处理案例篇

    在之前发布的<墨天轮最受欢迎的技术文档-容灾备份篇>中,大家说想看故障处理案例篇的内容,这不!编辑部快马加鞭给大家整理来了,希望能够帮助到大家. 数据库故障可能出现在内存.网络.CPU.硬 ...

  3. Ewald求和在分子静电势能计算中的应用

    技术背景 分子动力学模拟中,计算周期性边界条件的静电势常被视作计算的瓶颈之一.形式上是比较容易的,例如不考虑周期性边界条件的话,静电势能就是: \[E=\frac{1}{4\pi\epsilon_0} ...

  4. 何为ORM框架?和ADO.NET 对比

    百度:ORM(Object Relational Mapping)框架采用元数据来描述对象与关系映射的细节,元数据一般采用XML格式,并且存放在专门的对象一映射文件中.简单理解为一种框架的格式 . 只 ...

  5. RocketMQ 在小米的多场景灾备实践案例

    本文作者:邓志文.王帆 01为什么要容灾? 在小米内部,我们使用 RocketMQ 来为各种在线业务提供消息队列服务,比如商城订单.短信通知甚至用来收集 IoT 设备的上报数据,可以说 RocketM ...

  6. redis配置启动测试

    解压安装redis tar -xzvf redisxxx.xx生成解压目录 进入解压目录:执行命令 make make install 安装成功: redis默认安装位置/usr/local/bin ...

  7. 从零开始学逆向CTF比赛,免费参加,欢迎来玩!

    大家好,我是轩辕. 告诉大家一个好消息:我准备了一次逆向CTF比赛,面向所有人开放,无需购买课程,优秀的小伙伴还有奖励,参赛方式在文末会介绍,欢迎大家一起来玩. 举办这次CTF比赛,是为了检验大家从零 ...

  8. C++递归创建文件夹

    根据传入的参数递归进行目录的创建. 函数描述: 递归创建目录. 入参: 所要创建的目录. 返回值: 创建成功,返回TRUE:否则返回FALSE. 1 BOOL CreateDirTree(LPCTST ...

  9. 《机器学习实战》(Machine Learning in Action)

    地址: https://www.manning.com/books/machine-learning-in-action 代码地址: https://www.manning.com/downloads ...

  10. 3.2 Linux文件系统到底有什么用处?

    Linux 上常见的文件系统是EXT3或EXT4,但这篇文章并不准备一上来就直接讲它们,而希望结合Linux操作系统并从文件系统建立的基础--硬盘开始,一步步认识Linux的文件系统. 1.机械硬盘的 ...