本蒟蒻使用 (加权)并查集的玄学思路,爆了30,求大佬查错
查看原帖
本蒟蒻使用 (加权)并查集的玄学思路,爆了30,求大佬查错
68884
jiangyanheng楼主2020/11/23 19:02
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;
const int N=1e5+234;
int father[N];
bool dat[N];
int find(int f){
	if (f==father[f]) return f;
	else{
		int tmp=father[f];
		father[f]=find(father[f]);
		dat[f]+=dat[tmp];
		return father[f];
	}
}
inline int unionn(int a,int b,int sig){//只有 | 和 &运算需要合并
	//sig表示将哪个与哪个合并,以及合并后的影响情况 
	a=find(a),b=find(b);
//	printf("%d %d\n",a,b);
	if (a==b) return 0;
	switch(sig){
		case 0:{//两个都影响
			//对应 0|0 和 1&1 的情况 
			father[a]=b;//那就随便一合并,顺序不用管 
			return 0;
			break;
		}
		case 1:{//只有第一个影响 
			// 1|0 0&1 
			father[b]=a;
			dat[b]=1;//不影响就打1
			return 1; 
			break;
		}
		case 2:{//只有第二个影响 
			// 0|1 1&0
			father[a]=b;
			dat[a]=1;
			return 2;
			break;
		}
		case 3:{//两个都不影响 
			//1|1 0&0
			father[a]=b;
			dat[a]=1;
			dat[b]=1;
			return 0; 
			break;
		}
	}
}
int n;
inline string s_in(){
	string s;
	s="";
	char c=getchar();
	while(c!='\n'){s+=c;c=getchar();}
	return s;
}
inline int f_in(){
	int f=0;char t=1,c=getchar();
	while(c<'0' || c>'9'){if (c=='-') t=-1;c=getchar();}
	while('0'<=c && c<='9'){f=f*10+c-'0';c=getchar();}
	return f*t;
}
inline int getnum(int &i,string s){
	int f=0;
	while('0'<=s[i] && s[i]<='9'){f=f*10+s[i]-'0';i++;}
	i--;
	return f;
}
bool isnum(char c){if ('0'<=c && c<='9') return true;else return false;}
bool isopr(char c){if (c=='|' || c=='&' || c=='!') return true;else return false;}
string s;
int num[N];
stack<int> stk;//值栈 
stack<int> idx;//下标栈 
int main(){
	s=s_in();
	int l=s.length();
//	printf("%d\n",l);
//	cout<<s<<endl;
//	system("pause");
	int n=f_in();
	for(int i=1;i<=n;i++){
		father[i]=i;
		dat[i]=0;
	}
	for(int i=1;i<=n;i++){
		num[i]=f_in();
	}
	for(int i=0;i<l;i++){
//		printf("i:%d\n",i);
		
		if (i==27){
			int tmp1=stk.top();stk.pop();
			int id1=idx.top();idx.pop();
//			printf("tmp1:%d id1:%d\n",tmp1,id1);
			int tmp2=stk.top();stk.pop();
			int id2=idx.top();idx.pop();
//			printf("tmp2:%d id2:%d\n",tmp2,id2);
			stk.push(tmp2);stk.push(tmp1);
			idx.push(id2);idx.push(id1);
		}
		
		if (isnum(s[i])){
			int id=getnum(i,s);
			stk.push(num[id]);
			idx.push(id);
			continue;
		}
		if (isopr(s[i])){
			int tmp1=stk.top();stk.pop();
			int id1=idx.top();idx.pop();
			if (s[i]=='!'){
				tmp1=!tmp1;//取反就是原样压回去 
				stk.push(tmp1);
				idx.push(id1);
			}
			if (s[i]=='|' || s[i]=='&'){
				int tmp2=stk.top();stk.pop();
				int id2=idx.top();idx.pop();
				int tag=0;
				if (s[i]=='|'){
					if (tmp1) tag+=1;//
					if (tmp2) tag+=2;//tmp2才是靠前的变量 
					stk.push(tmp1|tmp2);
				}
				if (s[i]=='&'){
//					printf("a\n");
					if (!tmp1) tag+=2;
					if (!tmp2) tag+=1;
					stk.push(tmp1&tmp2);
				}
//				printf("b\n");
				int la=unionn(id1,id2,tag);
//				printf("c\n");
				if (la==1) idx.push(id1);
				else if (la==2) idx.push(id2);
				else idx.push(id1);
			}
		}
	}
	int ans=stk.top();
//	printf("%d\n",ans);
	for(int i=1;i<=n;i++){
		find(i);
//		printf("%d ",dat[i]);
	}
//	system("pause");
	int p=f_in();
	for(int i=1;i<=p;i++){
		int a=f_in();
		if (dat[a]) printf("%d\n",ans);
		else printf("%d\n",!ans);
	}
	return 0;
}

请大佬无视未删除的调试代码

2020/11/23 19:02
加载中...