这篇文章上次修改于 231 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

题目传送门

(题目真的长)

简化题意:在计算逻辑表达式时,会出现$1 \mathbin{|} b$ 和 $0 \mathbin{\&} b$ 的情况(也就是短路),后面的 $b$ 并不计算,需要你统计这类情况出现的次数,因为 $b$ 不用计算,所以计算$b$造成的短路不用计入最终的统计。

思路分析:如果直接将表达式转换为表达式树,为每个节点维护 $2$ 个值对应两种短路,在递归计算的时候,可以非常方便的维护出当前节点的 $2$ 个值,也就是有没有短路决定加不加 $1$,在相应的加上下面计算过程中产生的短路。

警钟长鸣:因为递归容易造成爆栈,所以可以转换为后缀表达式进行计算,即可AC。

细节处理1:中缀转成后缀表达式只用从前往后看,操作数直接加入后缀表达式序列,操作符就在栈中把优先级比他高的弹出大后缀表达式序列,再把这个运算符加入栈中,左括号直接加入栈,右括号弹栈到上一个左括号。

细节处理2:后缀表达式的计算是一个栈模拟的过程,遇到运算数直接加入,遇到运算符弹出 $2$ 个,再加入计算所得的答案。

差不多了,贴代码:

#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;
long long read(){
	char temp=getchar();
	long long f=1,x=0;
	while('0'>temp||temp>'9'){
		(temp=='-')?(f=-1):0;
		temp=getchar();
	}
	while('0'<=temp&&temp<='9'){
		x=(x<<3)+(x<<1)+(temp^'0');
		temp=getchar();
	}
	return f*x;
}
class node{
	public:
		int ansa,ansb;
		int i;
		node(int a,int b,int j){
			ansa=a;
			ansb=b;
			i=j;
		}
		node(){
			ansa=ansb=i=0;
		}
};
stack<node>calc;
stack<char>ex;
int nowb=0;
int ansa=0,ansb=0;
char bac[1000005];
int dfs(){
	for(int i=1;i<=nowb;i++){
		if(i==nowb-1){
			i=nowb-1;
		}
		if(bac[i]=='1'||bac[i]=='0'){
			calc.push(node({0,0,i})); 
		}else if(bac[i]=='|'){
			node a=calc.top();
			calc.pop();
			node b=calc.top();
			calc.pop();
			node in;
			in.i=i;
			bac[i]=(((bac[a.i]-'0')||(bac[b.i]-'0'))+'0');
			if(bac[b.i]=='1'){
				in.ansa=b.ansa;
				in.ansb=b.ansb+1;
			}else{
				in.ansa=a.ansa+b.ansa;
				in.ansb=a.ansb+b.ansb;
			}
			calc.push(in);
		}else{
			node a=calc.top();
			calc.pop();
			node b=calc.top();
			calc.pop();
			node in;
			in.i=i;
			bac[i]=(((bac[a.i]-'0')&&(bac[b.i]-'0'))+'0');
			if(bac[b.i]=='0'){
				in.ansa=b.ansa+1;
				in.ansb=b.ansb;
			}else{
				in.ansa=a.ansa+b.ansa;
				in.ansb=a.ansb+b.ansb;
			}
			calc.push(in);
		}
	}
	ansa=calc.top().ansa;
	ansb=calc.top().ansb;
	return bac[calc.top().i]-'0';
}
int mian(){
// 	freopen("expr.in","r",stdin);
// 	freopen("expr.out","w",stdout);
	char temp=getchar();
	while(temp!=EOF){
		if(temp=='0'||temp=='1'){
			bac[++nowb]=temp;
		}else if(temp=='|'){
			while(ex.size()>0&&(ex.top()=='&'||ex.top()=='|')){
				bac[++nowb]=ex.top();
				ex.pop();
			}
			ex.push('|'); 
		}else if(temp=='&'){
			while(ex.size()>0&&ex.top()=='&'){
				bac[++nowb]=ex.top();
				ex.pop();
			}
			ex.push('&');
		}else if(temp=='('){
			ex.push('(');
		}else if(temp==')'){
			while(ex.size()>0&&ex.top()!='('){
				bac[++nowb]=ex.top();
				ex.pop();
			}
			ex.pop();
		}
		temp=getchar();
	}
	while(ex.size()>0){
		bac[++nowb]=ex.top();
		ex.pop();
	}
	printf("%d\n",dfs());
	printf("%d %d",ansa,ansb);
	return 0;
}

欢迎到博客查看其它题解。