zoukankan      html  css  js  c++  java
  • 「HNSDFZ暑期集训 测试1」「LuoguT36485」 括号(贪心

    Description


    给定一个由左括号'('和右括号')'组成的字符串s,其中第i个括号的权值为ai。

    我们定义一个括号序列t为合法括号序列,当且仅当满足下列条件之一:

    1.t为空串

    2.t=(A),其中A为一个合法括号序列

    3.t=AB,其中A,B均为合法括号序列

    比如(()()),()(())均为合法括号序列,但((), ())(不是合法括号序列。

    Input


    输入第一行一个整数n,表示s的长度。

    第二行一个长度为n,且由括号组成的字符串s。

    第三行n个整数,第i个整数ai表示第i个括号的值。

    Output


    输出仅一行一个整数,表示答案。

    Sample Input1


    6
    ())(()
    1 2 1 2 1 2

    Sample Output1


    7

    Sample Input2


    6
    ((()))
    2 1 -2 1 2 3

    Sample Output2


    8

    Hint


    40%的数据n<=20,0<=ai<=100

    接下来30%的数据 n<=2000,|ai|<=1e5

    接下来30%的数据 n<=2e5,|ai|<=1e3,左括号全都在右括号的左边

    题解


    官方题解:

    分情况讨论 
    n<=2000时 用dp,F [ i ] [ j ]表示前i个中有j个左括号时的最大值
    n >2000时,分别对左括号的值和右括号的值排序(cmp从大到小),用for循环从1走一遍,若a[i]+b[i]>0 ans+=a[i]+b[i],否则return.

    但是我的思路可以把n取到1e6并且不需要特殊性质啊!QAQ

    我们先假设现在已经从头开始扫了一段括号序列,并且前一段已经标记了最优的序列有哪些括号。对于现在新加进来的括号,我们仍然要试图维持当前选择最优。
    
    如果是左括号,我们不做任何处理(也做不了什么);
    
    如果是右括号,那么不外乎三种情况:
    
    1.不做任何处理;
    
    2.在这个右括号之前找一个未被选的左括号,与其配对(标记此左括号和右括号);
    
    3.在这个右括号之前找一个被选了的右括号,将其替代(清除前面的右括号的标记,并且标记新的右括号)
    
    只要在这三种操作中取一个最优操作,就仍然可以保持当前最优。

    那么,用一个for从头至尾循环,复杂度O(n),

    对每个当前括号,做以上判断,

    其中的往前找要求的括号的操作(2)和操作(3)可以用堆实现,复杂度O(logn)

    一共O(nlogn)

    代码://考场代码 因为可以水到分所以懒得写堆了(其实可以直接调用priority_queue 也很方便)

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cmath>
      5 using namespace std;
      6 int s[200007];
      7 int q[200007];
      8 bool sf[200007];
      9 int a[200007];
     10 int b[200007];
     11 bool cmp(int qaq,int qwq)
     12 {
     13     return qaq>qwq;
     14 }
     15 int main()
     16 {
     17     int n;
     18     cin>>n;
     19     if(n<2001)
     20     {
     21     for(int i=1;i<=n;++i)
     22     {
     23         char x;
     24         cin>>x;
     25         if(x=='(')s[i]=1;
     26         else s[i]=2;
     27     }
     28     for(int i=1;i<=n;++i)
     29     {
     30         cin>>q[i];
     31         //cout<<i<<" "<<s[i]<<" "<<a[i]<<endl;
     32         if(s[i]==2)
     33         {
     34             int u=-99999999,pu=0;
     35             for(int j=i-1;j;--j)
     36             if(s[j]==1&&!sf[j])
     37             {
     38                 if(q[j]>u){u=q[j];pu=j;}
     39             }
     40             int v=99999999,pv=0;
     41             for(int j=i-1;j;--j)
     42             if(s[j]==2&&sf[j])
     43             {
     44                 if(q[j]<v){v=q[j];pv=j;}
     45             }
     46             //cout<<u<<" "<<pu<<" "<<v<<" "<<pv;
     47             if(pu&&pv)
     48             {
     49             if(u+q[i]>=q[i]-v&&u+q[i]>0)
     50             {
     51                 sf[pu]=1;sf[i]=1;
     52             }
     53             else if(q[i]-v>u+q[i]&&q[i]-v>0)
     54             {
     55                 sf[pv]=0;sf[i]=1;
     56             }
     57             }
     58             else
     59             {
     60                 if(pu&&u+q[i]>0)
     61                 {
     62                     sf[pu]=1;sf[i]=1;
     63                 }
     64                 else if(pv&&q[i]-v>0)
     65                 {
     66                     sf[pv]=0;sf[i]=1;
     67                 }
     68             }
     69             //cout<<endl;
     70         }
     71     }
     72     int ans=0;
     73     for(int i=1;i<=n;++i)
     74     if(sf[i]){ans+=q[i];}
     75     cout<<ans;//强大怪!!! 
     76     return 0;
     77     }
     78     else
     79     {
     80     for(int i=1;i<=n;++i)
     81     {
     82         char x;
     83         cin>>x;
     84         if(x=='(')s[i]=1;
     85         else s[i]=2;
     86     }
     87     int toa=0,tob=0;
     88     for(int i=1;i<=n;++i)
     89     {
     90         int x;
     91         scanf("%d",&x);
     92         if(s[i]==1)a[++toa]=x;
     93         else b[++tob]=x;
     94     }
     95     sort(a+1,a+toa+1,cmp);
     96     sort(b+1,b+tob+1,cmp);
     97     int ans=0;
     98     for(int i=1;i<=min(toa,tob);++i)
     99     {
    100         if(a[i]+b[i]>0)ans+=(a[i]+b[i]);
    101         else {cout<<ans;return 0;}
    102     }
    103     cout<<ans;//强大怪!!! 
    104     return 0;
    105     }
    106 }
    107 //注释强大怪 你会rp++

    UPD

    $O(nlogn)$的堆写法↓

     1 /*
     2 qwerta 
     3 T36485 括号 Accepted 
     4 100
     5 代码 C++,0.7KB
     6 提交时间 2018-11-05 20:42:18
     7 耗时/内存 442ms, 2124KB
     8 */
     9 #include<iostream>
    10 #include<cstdio>
    11 #include<queue>
    12 using namespace std;
    13 char ch[200003];
    14 int v[200003];
    15 priority_queue<int,vector<int>,greater<int> >r;//r放右括号
    16 priority_queue<int>l;//l放左括号
    17 int main()
    18 {
    19     //freopen("a.in","r",stdin);
    20     ios::sync_with_stdio(false);
    21     int n;
    22     cin>>n;
    23     for(int i=1;i<=n;++i)
    24     cin>>ch[i];
    25     for(int i=1;i<=n;++i)
    26     cin>>v[i];
    27     //
    28     int ans=0;
    29     for(int i=1;i<=n;++i)
    30     {
    31         if(ch[i]=='(')
    32         {
    33             l.push(v[i]);
    34         }
    35         else
    36         {
    37             int x,y;
    38             if(l.empty())x=-1;//赋成-1不碍事儿
    39             else x=v[i]+l.top();
    40             if(r.empty())y=-1;
    41             else y=v[i]-r.top();
    42             if(x>=y&&x>=0)//找个没用过的左括号
    43             {
    44                 ans+=x;
    45                 l.pop();
    46                 r.push(v[i]);
    47             }
    48             else if(y>=x&&y>=0)//替代一个用过的右括号
    49             {
    50                 ans+=y;
    51                 r.pop();
    52                 r.push(v[i]);
    53             }
    54         }
    55     }
    56     cout<<ans;
    57     return 0;
    58 }
  • 相关阅读:
    Sql Server2005新特性及性能
    Sql Server Debugger
    .关于 WCF Binding 中 OpenTimeout, CloseTimeout, SendTimeout, ReceiveTimeout 的解释(转载)
    LightSwitch™初体验
    WinDbg / SOS Cheat Sheet
    《Dissecting SQL Server Execution Plans》随记
    轻松掌握用SQL来合并查询
    Oracle:存储过程的使用
    Eclipse和Tomcat的版本问题已解决
    oracle:触发器的使用
  • 原文地址:https://www.cnblogs.com/qwerta/p/9379746.html
Copyright © 2011-2022 走看看