jzoj 3814 天黑黑

Description

我走在每天必须面对的分岔路/我怀念过去单纯美好的小幸福/爱总是让人哭/让人觉得不满足/天空很大却看不清楚/好孤独/天黑的时候/我又想起那首歌/突然期待下起安静的雨/原来外婆的道理早就唱给我听/下起雨/也要勇敢前行/我相信/一切都会平息/我现在好想回家去/天黑黑/欲落雨/天黑黑/黑黑
当整个世界陷入黑暗的时候,身为光明之神的Zyh想要用自己的若干个能量源和若干个集流器将这些能量源并成一个最大的能量源,这样他就可以造出最大的灯来照亮整个世界。
具体地来说每个能量源可以直接给出Ei的能量。而每个集流器是由两个接受端口和一个输出端口组成的。集流器有两种:A类和B类。A类是叠加集流器,可以将两个接收端口的能量叠加并输出。B类是取代集流器,可以将两个接受端口的能量较大那个输出。
现在有n-1个集流器,n个能量源。Zyh给出了集流器的连接方式,他想知道怎样放置能量源,能够使最后的输出最大化。

Input

第一行是一个字符串,表示连接的方式。给出的形式是这样的:X,表示一个单独的输出能量源的放置处;AS1S2,其中S1和S2表示两个输出能量,A表示使用叠加集流器将能量并成一个,然后这本身也成为一个新的输出能源;BS1S2也是同理,只不过是使用取代集流器。并且保证A和B的个数为n-1个。X的个数为n个。
第二行是n个正整数,表示这几个能量源。

Output

一个数,表示最大的输出能源。

Sample Input

输入1:
BXBXX
8 2 3
输入2:
AXBXX
8 2 3

Sample Output

输出1:
8
输入2:
11

Data Constraint

对于20%的数据 n<10
对于60%的数据 n<=3000
对于100%的数据 n<=200000 Ei<=10000

解题思路

如果直接想方设法的用贪心使结果最大化,要考虑的细节很多,有很多反例,没有较好的贪心策略(开始怎么也想不出,还怀疑是网络流。。。)
其实可以不考虑最大的结果,而考虑可以最多可以剩下多少个能量源,然后把最大的全放进去就可以使结果最大化了。
问题就被简化了,若是A集流器,把结果相加,若是B集流器,则取较大的,输入的X当做1处理。由于包含嵌套运算,用栈来处理,每发现栈顶有两个非运算的结果,合并两个结果,放到原运算符的位置,按照输入顺序处理完整个字符串,就可以知道最多可以保留多少个能量源,计算出最大的输出量。

Source Code

const
  maxn=2000000;

var
  a,s:array[0..maxn] of longint;
  c,p,q:ansistring;
  n,m,b,k:longint;
  ans:int64;

procedure qsort(l,r:longint);
var
  i,j,mid:longint;
begin
  i:=l;
  j:=r;
  mid:=a[(l+r) div 2];
  repeat
    while (a[i]>mid) and (i<r) do inc(i);
    while (a[j]<mid) and (j>l) do dec(j);
    if (i<=j) then
      begin
        a[0]:=a[i];
        a[i]:=a[j];
        a[j]:=a[0];
        inc(i); dec(j);
      end;
  until i>j;
  if (i<r) then qsort(i,r);
  if (l<j) then qsorT(l,j);
end;

function max(x,y:longint):longint;
begin
  if (x>y) then exit(x)
           else exit(y);
end;

procedure init;
var
  i,j:longint;
begin
  readln(c);
  m:=length(c);
  for i:=1 to m do if (c[i]='X') then inc(n);
  for i:=1 to n do
    read(a[i]);
end;

procedure main;
var
  i,j:longint;
begin
  j:=0;
  for i:=1 to m do
    begin
      inc(j);
      case c[i] of
        'A':s[j]:=0;
        'B':s[j]:=-1;
        'X':s[j]:=1;
      end;
      while (s[j]>0) and (s[j-1]>0) do
        begin
          if (s[j-2]=0) then s[j-2]:=s[j]+s[j-1];
          if (s[j-2]=-1)then s[j-2]:=max(s[j],s[j-1]);
          j:=j-2;
        end;
    end;
end;

begin
  init;
  qsort(1,n);
  main;
  ans:=0;
  for k:=1 to s[1] do
    ans:=ans+a[k];
  writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值