社区讨论

随机生成16万倍测试点1范围的数据都对,但测试点1TLE

P9869[NOIP2023] 三值逻辑参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mhj11yvx
此快照首次捕获于
2025/11/03 18:58
4 个月前
此快照最后确认于
2025/11/03 18:58
4 个月前
查看原帖
题目P9869 题目传送门 本蒟蒻遇到的标题所述的困难;完全无从下手了,求解答或易懂的hack
fa数组是模拟赋值过程
pa是记录(最终)祖先,应该是在实现一种带负号的并查集
顺便一提,哪怕我把输入的负号当+号都TLE
因为我是灰号,哪怕大佬是把测试点一下载发出来都是对我莫大的帮助
(之前的求助帖不好,删了重发,现在在这个题上已经用了20h了)
CPP
#include <bits/stdc++.h>
#define T (N-1)
#define F (N-2)
#define U (N-3)
using namespace std;
int func();
int find(int k);
int unite(int i,int j);
const int N=100009;
int bug, times=0,nowfind;
int xf[N],xpa[N],xv[N];//x_father,x_grandgrand...pa,x_value,value=T/F/U
int main(){
//	freopen("C:\\Users\\30239\\Desktop\\dev-C++\\tribool\\tribool7.in","r",stdin);
//	freopen("C:\\Users\\30239\\Desktop\\dev-C++\\tribool\\myans.txt","w",stdout);
	int c,t;
	cin>>c>>t;
	for(int i=1;i<=t;i++){
		func();
	}
	return 0;
}
int func(){
	for(int i=1;i<N;i++){
		xf[i]=i;
		xpa[i]=i;
		xv[i]=i;
	}
	int n,m,i,j,cnt=0;
	char v;
	cin>>n>>m;
	for(int k=1;k<=m;k++){
		cin>>v;
		if(v=='U') {cin>>i;xf[i]=U;}
		if(v=='F') {cin>>i;xf[i]=F;}
		if(v=='T') {cin>>i;xf[i]=T;}
		if(v=='+') {
		    cin>>i>>j;
		    xf[i]=(xf[j]);
		}
		if(v=='-') {
		    cin>>i>>j;
		    xf[i]=-(xf[j]);                         
		}
	}
	for(int k=1;k<=n;k++){
//		cout<<k<<"-> "<<xf[k]<<endl;
	}
	
	for(int k=1;k<=n;k++){
		unite(k,xf[k]);
	}
    for(int k=1;k<=n;k++){
    	if(xpa[k]==-k) xpa[k]=U;
	}
	for(int k=1;k<=n;k++){
		if(find(k)==U||find(k)==-U) cnt++;
	}
	cout<<cnt<<endl;//exit(0);
}
int unite(int i,int j){//把i祖先接到j祖先上 
    int m=find(xpa[i]);
    int sgn=m/abs(m);
    xpa[abs(m)]=find(j)*sgn;
	if(xpa[i]==-i) xpa[i]=U;
//      xpa[i]=find(j);if(xpa[i]==-i) xpa[i]=U;

}
int find(int k){//find(k)返回k祖先编号乘上标记与k是否相同的(-1) ,并把 途径节点都连接到祖先上 
	if(k==U) return U;
    if(k==F) return F;
    if(k==T) return T; 
	int sgn=k/abs(k);
	k=k*sgn;
	if(xpa[k]==-k){
		xpa[k]=U;
		return k;		
	}
	if(xpa[k]==k) return k*sgn;
	return sgn*(xpa[k]=find(xpa[k]));
}





















回复

2 条回复,欢迎继续交流。

正在加载回复...