51nod 1476 括号序列的最小代价 (括号题套路+反悔贪心)

题意:给一串只有‘(‘ , ‘)‘ , ‘?‘ 的括号序列,每个?可以变成)或者(,代价分别为bi和ai,求变成合法序列的最小代价

思路:学习自最近的网络赛&&51nod贪心专题视频的思想,“反悔”,一般在获取收益有限制的情况下使用

先按某种“优”的策略贪心,如果不满足限制条件了,取一个修改后代价尽可能小的状态修改成满足条件的状态,得到新的满足限制下的最优解

这种贪心常常可以借助优先队列实现

然后是括号题的套路:把(当做1,把)当做-1,做前缀和

这题中,先当做所有的?都换成右括号,这是显然的,顺推只要前缀和小于0就是不合法,需要“反悔”,优先队列维护ai和bi的差值,每次取换成左括号最便宜的问号转换

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<queue>
 6 #define LL long long
 7 #define debug(x) cout << "[" << x << "]" << endl
 8 using namespace std;
 9
10 const int mx = 50010;
11 char s[mx];
12 LL a[mx], b[mx];
13
14 int main(){
15     priority_queue<LL> q;
16     int sum = 0;
17     LL ans = 0;
18     scanf("%s", s);
19     int len = strlen(s);
20     for (int i = 0; i < len; i++)
21         if (s[i] == ‘?‘) scanf("%lld%lld", &a[i], &b[i]);
22     for (int i = 0; i < len; i++){
23         if (s[i] == ‘(‘) sum++;
24         else {
25             sum--;
26             if (s[i] == ‘?‘) {
27                 ans += b[i];
28                 q.push(b[i]-a[i]);
29             }
30         }
31         if (sum < 0){
32             if (q.empty()){
33                 printf("-1\n");
34                 return 0;
35             }
36             ans -= q.top();
37             sum += 2;
38             q.pop();
39         }
40     }
41     if (sum != 0) printf("-1\n");
42     else printf("%lld\n", ans);
43     return 0;
44 }

原文地址:https://www.cnblogs.com/QAQorz/p/9595184.html

时间: 2024-08-10 07:16:11

51nod 1476 括号序列的最小代价 (括号题套路+反悔贪心)的相关文章

括号序列的最小代价

题意 查看原题 这里有一个关于合法的括号序列的问题. 如果插入"+"和"1"到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的.例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(()))("是不合法的.我们这有一种仅由"(",")"

2017-5-14 湘潭市赛 Parentheses 转化思想+贪心 使括号序列合法的最小花费。满足前面左括号的数量&gt;=有括号的数量。

Parentheses Accepted : 8 Submit : 19 Time Limit : 3000 MS Memory Limit : 65536 KB Parentheses Bobo has a very long sequence divided into n consecutive groups. The i-th group consists of li copies of character ci where ci is either "(" or ")

51nod 1125 交换机器的最小代价

基准时间限制:1 秒 空间限制:131072 KB 有N台机器重量各不相等,现在要求把这些机器按照重量排序,重量从左到右依次递增.移动机器只能做交换操作,但交换机器要花费一定的费用,费用的大小就是交换机器重量的和.例如:3 2 1,交换1 3后为递增排序,总的交换代价为4.给出N台机器的重量,求将所有机器变为有序的最小代价.(机器的重量均为正整数) Input 第1行:1个数N,表示机器及房间的数量.(2 <= N <= 50000) 第2 - N + 1行:每行1个数,表示机器的重量Wi.(

POJ 3270. Cow Sorting &amp; 51nod 1125 交换机器的最小代价

根据题意,需要交换的部分会形成若干个不相交的环,独立处理每个环. 每个环可以用环内的最小值去和其它元素交换,或者用全局最小值和环上最小值交换,做一遍再交换回去. #include <cstdio> #include <cstring> const int MOD = 9973; int m, n, k; void M(int &a) { if (a >= MOD) a -= MOD; if (a < 0) a += MOD; } struct Mat { int

喵哈哈村的括号序列

描述 喵哈哈村的括号序列和外界的括号序列实际上是一样的. 众所周知"()"这样的,就是一个标准的括号序列:"()()()()"这样也是括号序列:"((()))()"这样也是一个合法的括号序列.但是"((("这样,就不是一个合法的括号序列了. 现在沈宝宝非常好奇,给你一个字符串,请从中找出最长的合法括号序列出来. 不知道你能找到吗? 输入 第一行一个T,表示有T组数据.接下来T行,每一行都是一个字符串.保证字符串的长度小于100

Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】

校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,K=1,读入l.r表示在区间[l,r]中种上一种树,每次操作种的树的种类都不同 K=2,读入l,r表示询问l~r之间能见到多少种树 (l,r>0) 格式 输入格式 第一行n,m表示道路总长为n,共有m个操作 接下来m行为m个操作 输出格式 对于每个k=2输出一个答案 样例1 样例输入1 5 4 1 1

算法题:括号匹配(小中大括号序列)

括号序列由( )[ ]{ }组成,不合法的括号序列由( { ) },[ } { ],等等.编程实现一个函数,检查一个括号序列是否是合法的括号序列. 解法: 思路和"后缀表达式的求解"相似.我们借助栈,每读一个括号,如果是左括号,那么入栈,然后继续读下一个括号:如果是右括号,那么就要看看这个右括号和栈顶的括号是否匹配:如果匹配,那么弹出栈顶的括号,继续读下一个括号.当栈变空时,说明此括号序列是合法的. public class Test05 { public static boolean

【堆栈模板】括号序列

题目描述 一个由小括号组成的字符串可以被称为一个括号序列.但一个括号序列可能并不满足括号匹配的要求.因此,我们可以进一步将满足括号匹配的括号序列成为"标准的括号序列.例如字符串")((())"是一个括号序列但不是标准的括号序列,而字符串"()(())"是一个标准的括号序列.给定一个括号序列,你需要对求出:这个括号序列的所有不同的子串中,有多少个是标准的括号序列?一个括号序列的子串指的是这个序列从某个位置起始.到某个位置截止的子字符串.如果两个子串拥有不同的

BZOJ2209: [Jsoi2011]括号序列

传送门 splay练习. 考虑把括号序列转化成类似于区间最大/最小值的情况. 显然我们可以知道括号序列消完的情况肯定是$a$个)和$b$个(,那么把这些括号全部合法化的代价显然就是$\frac{a+1}{2}+\frac{b+1}{2}$. 接着我们可以把'('变为1,把')'变为-1,然后每次取左区间的连续最小值,右区间的连续最大值,就是$a$与$b$的大小. 因为存在区间翻转,所以需要把左/右区间的连续最大/小值都搞出来. splay即可. //BZOJ2209 //by Cydiater