湘潭邀请赛G- Parentheses(贪心,思维)

来源:互联网 发布:linux查看jvm版本 编辑:程序博客网 时间:2024/05/29 19:06

Parentheses

Bobo has a very long sequence divided into n  consecutive groups. The i -th group consists of l i   copies of character c i   where c i   is either "(" or ")".

As the sequence may not be valid parentheses sequence, Bobo can change a character in thei -th group from "(" to ")" (and vice versa) with cost d i  . He would like to know the minimum cost to transform the sequence into a valid one.

Note:

  • An empty string is valid.
  • If S  is valid, (S)  is valid.
  • If U,V  are valid, UV  is valid.

Input

The input contains zero or more test cases and is terminated by end-of-file. For each test case:

The first line contains an integer n . The i -th of the following n  lines contains l i ,c i ,d i  .

  • 1n10 5  
  • 1l 1 +l 2 ++l n 10 9  
  • l 1 +l 2 ++l n   is even.
  • 1d i 10 9  
  • The sum of n  does not exceed 10 6  .

Output

For each case, output an integer which denotes the result.

Sample Input

41 ( 11 ( 21 ( 31 ) 42500000000 ) 1000000000500000000 ( 1000000000

Sample Output

2500000000000000000

Note

For the first sample, Bobo should change only the character in the second group.

For the second sample, Bobo should change half of characters in both groups.


Source

XTU OnlineJudge 

思路:

这道题一开始想的,思路很乱,就是不知道什么时侯该吧左括号变为右括号,什么时候把右括号变为左括号,要考虑道后面出现的情况,后面根据题解的启发,我想到可以,先把右括号变为左括号,根据括号总和和左括号数来决定,左括号的数要大于等于(sum+1)/2为什么要sum+1呢,当sum为奇数时,比如7,这时如果不是sum+1的话,那么左括号的个数为3,然后总数加一的话,新加入的·一组如果话费更小了的话,那么选择的话是后面加入进来的,而不是前面的,就是错了,将右括号变为左括号后,然后在将多余的左括号变为右括号,但是这样做的话会存在一个很麻烦的地方,就是到第二次扫的时候,也就是将多余的右括号变为左括号的时候,要记录上一次什么地方改变了,因为有可能一组中没有全部变完,也可能全部变完,记录的时候会很麻烦,所以我们可以考虑这种做法,一开始把所有的左括号变为右括号,然后把花费取相反数,这样的话就只用扫一次了,不用记录哪个位置变成什么了,然后用一个优先队列维护一下,当前最小花费就行了(优先队列好像不能只重载大于号)


ac代码

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<sstream>#include<queue>#define LL long longusing namespace std;const int maxn = 1e5+10000;struct node{    LL num,cost;    char m[2];    bool operator < (const node &p) const    {        return this->cost>p.cost;    }}t[maxn];int n;int main(){    while(~scanf("%d",&n))    {priority_queue<node>Q;    LL pre = 0 , sum = 0,ans = 0;        for(int i = 1 ;i<=n;i++)        {            scanf("%I64d%s%I64d",&t[i].num,t[i].m,&t[i].cost);            if(t[i].m[0]=='(')            {                t[i].m[0]=')';                ans+=t[i].cost*t[i].num;                t[i].cost = -t[i].cost;            }        }        while(!Q.empty()) Q.pop();        for(int i = 1 ;i <= n;i++)        {            sum += t[i].num;                Q.push(t[i]);            LL need  = (sum+1)/2 - pre;            if(need>0)            {                while(!Q.empty()&&need)                {                    node tmp = Q.top();                    Q.pop();                    if(need>=tmp.num)                    {                        need -= tmp.num;                        ans += tmp.num*tmp.cost;                        pre+=tmp.num;                        //Q.pop();                    }                    else                    {                        tmp.num -= need;                        pre+=need;                        ans += need*tmp.cost;                        Q.push(tmp);                          need = 0;                    }                }            }        }        cout<<ans<<endl;        //cout<<pre<<' '<<sum/2<<endl;    }}