社区讨论
随机生成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
因为我是灰号,哪怕大佬是把测试点一下载发出来都是对我莫大的帮助
#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 条回复,欢迎继续交流。
正在加载回复...