[优先队列][堆] Luogu P4505 组合子逻辑

题目描述

组合子逻辑是 Moses Schönfinkel 和 Haskell Curry 发明的一种符号系统,用于消除数理逻辑中对于变量的需要。本题考察一种与真实世界的组合子演算略有差别的组合子系统。

一个组合子项是下列形式之一:

PP

(E_1\;E_2)(E1E2)

其中 PP 表示一个基本函数,E_1E1以及E_2E2表示一个组合子项(可以相同)。不满足以上形式表达式均非组合子项。

我们将一个组合子项 EE 的参数个数 np(E)np(E)如下:

np(P)np(P) = 基本函数 PP 的参数个数;

np((E_1\;E_2)) = np(E_1) - 1np((E1E2))=np(E1)1。

本题中,我们用一个正整数同时表示一个基本函数,以及该基本函数的参数个数。

对于一个组合子项 EE,如果它和它包含的所有组合子项的参数个数 npnp 均为正整数,那么我们称这个 EE 为范式。

我们经常组合子项简化表示:如果一个组合子项EE含有连续子序列(… ((E_1\;E_2)\;E_3) …E_n)(((E1E2)E3)En) (其中 n ≥ 3n3),其中E_kEk表示组合子项(可以是简化表示的),那么将该部分替换为(E_1\;E_2\;E_3 … E_n)(E1E2E3En),其他部分不变,得到表达式 EE 的一个简化表示。一个组合子项可以被简化表示多次。

给定一个基本函数序列,问至少需要添加多少对括号,才能使得该表达式成为一个范式的简化表示(即满足范式的性质);如果无论如何怎样添加括号,均不能得到范式的简化表示,输出-11。

题解

  • 题面真的害死人
  • k 表示当前的最大值还能再包含多少位,当前的最大值不一定要包含当前位,只要求出正确结果即可

代码

 1 #include <queue> 
 2 #include <cstdio> 
 3 #include <cstring>
 4 #include <iostream>
 5 using namespace std;
 6 int T,n,a[2000010];
 7 priority_queue<int> Q;
 8 int main()
 9 {
10     for (scanf("%d",&T);T;T--)
11     {
12         scanf("%d",&n);
13         for (int i=1;i<=n;i++) scanf("%d",&a[i]);
14         if (n==1) { puts(a[1]?"0":"-1"); continue; }
15         int k=a[1]-1,ans=1; 
16         while (!Q.empty()) Q.pop();
17         for (int i=2;i<=n;i++)
18         {
19             if (k) k--;
20             else 
21             {
22                 if (Q.empty()||Q.top()<2) { ans=-1; break; }
23                 ans++,k=Q.top()-2,Q.pop();
24             }
25             Q.push(a[i]);
26         }
27         printf("%d\n",ans); 
28     }
29 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/11280301.html