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 ...
随机推荐
- 使用 nuxi preview 命令预览 Nuxt 应用
title: 使用 nuxi preview 命令预览 Nuxt 应用 date: 2024/9/8 updated: 2024/9/8 author: cmdragon excerpt: 摘要:本文 ...
- Mongodb入门5
最近在用MongoDBKoa2做个小项目,记录一下: 首先,如何连接线上数据库: const url = `mongodb://user:pwd@ipaddr:27017/Blog`; const m ...
- TypeScript – Get Started
前言 我学 TypeScript 的时候是 Angular 2.0 beta 的年代... 现在 Angular 都快 14 了. 但由于已经有 1 年半没有写 Angular 和 TypeScrip ...
- 开发板、windows、虚拟机互相ping通/ VMNET0、VMNET1、VMNET8释义
当前环境:板子通过网线连接windows 问题: 我当前的板子可以ping通windows,windows也能ping通ubuntu.但是板子却ping不通ubuntu. 原因: ubuntu通过NA ...
- k8s-部署
目录 1 k8s 组件功能介绍 1.2 K8s 集群API: kube-apiserver 1.3 K8s 调度程序:kube-scheduler 1.4 K8s 控制器:kube-controlle ...
- USB协议详解第10讲(USB描述符-报告描述符)
1.报告描述符的概念和作用 开门见山,报告描述符就是描述报告(HID接口上传输事务中的数据)的一组数据结构. 首先大家可能会问,报告又是什么?我们前面讲过,USB主机一般是以中断的方式向HID设备发送 ...
- Android Qcom USB Driver学习(十一)
基于TI的Firmware Update固件升级的流程分析usb appliction layers的数据 USB Protocol Package ①/② map to check password ...
- 7-11 leetcode 2612
请你编写一个异步函数,它接收一个正整数参数 millis ,并休眠这么多毫秒.要求此函数可以解析任何值. ps: promise 期约函数 (异步函数)的使用 ,promise 是一个对象 new ...
- excel导⼊功能的实现流程简要描述⼀下?
当时公司的场景⼤概⼀个excel⽂件⾥就⼏⼗条数据,量⽐较少,和后端商量之后制定了前端主导的⽅ 案,解析的过程放到了浏览器端做,当时是参考了⼀下vue-admin中的现成的⽅案 ⼤概流程是这样的,⼈事 ...
- DirectoryOpus插件:“照得标管理器”-海量照片分类管理好帮手!
照得标管理器 前言 名词解释:"照得标管理器",即:照片得到标签管理器,后文统一简称"照得标管理器"或"照得标". 注:请不要和抖 ...