恩首先说一下非正解的一种方法,可以在洛谷上骗到9个点(共11个点,两个TLE,若吸氧则可以骗到10个点)
该方法呢也是有一定的并查集思想,但在合并上并非路径压缩或是按秩合并,而是。。怎么说呢。。顺序合并??嗯差不多。大致解释一下呢就是再合并时将下面一堆的根节点的父亲节点指向被移动的叶子节点,且将该叶子节点的子节点指向下面一堆的根节点,每次输出时从读入的a开始向下遍历,知道叶子节点停止并输出,以下为非正解代码:
1 #include<set> 2 #include<map> 3 #include<list> 4 #include<queue> 5 #include<stack> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9 #include<vector> 10 #include<bitset> 11 #include<memory> 12 #include<utility> 13 #include<cstdio> 14 #include<sstream> 15 #include<iostream> 16 #include<cstdlib> 17 #include<cstring> 18 #include<algorithm> 19 using namespace std; 20 21 int n,ans; 22 int z[30005],y[30005]; 23 24 int get(){//快读 25 char c=getchar(); 26 int res=0; 27 while(c<'0'||c>'9'){ 28 c=getchar(); 29 } 30 while(c>='0'&&c<='9'){ 31 res=(res<<3)+(res<<1)+c-'0'; 32 c=getchar(); 33 } 34 return res; 35 } 36 37 inline int dep(int a){//求一个节点到叶子节点的深度 38 return a==y[a]?0:1+(dep(y[a])); 39 } 40 41 inline int top(int a){//求含a节点的树的根节点 42 return a==z[a]?a:top(z[a]); 43 } 44 45 inline int down(int a){//求含a节点的树的叶子节点 46 return a==y[a]?a:down(y[a]); 47 } 48 49 int main(){ 50 n=get(); 51 for(int i=1;i<=30000;i++){//初始化 52 z[i]=y[i]=i; 53 } 54 while(n--){ 55 char s; 56 cin>>s; 57 if(s=='M'){ 58 int a=get(),b=get();//移动一堆积木 59 a=down(a),b=top(b); 60 z[b]=a; 61 y[a]=b; 62 } 63 else{ 64 int a=get(); 65 int ans=0; 66 //printf("%d ",dep(a));//这句话跟下面两行是一样的意思,只是闲的没事干看看能不能变快一点。。 67 for(;a!=y[a];a=y[a])ans++; 68 printf("%d ",ans); 69 } 70 } 71 //for(int i=1;i<=6;i++){//调试用 72 // printf("%d %d %d ",z[i],y[i],dep(i)); 73 //} 74 return 0; 75 }
好的,那么这个非正解的骗分代码就写好了,但是这个代码即使吸了氧还是有一个点会超时,那么我们就需要引出正解:带权并查集
但是。。。
时候不早了,我这题正解编了好长时间还是不对。。。
so有时间再把这个坑补上吧。。。(希望我还能记得)
先睡了,晚安~~
以上写就与19.7.4 3:30
19.7.4 7:27补坑ing
好的我来补坑了,由于我们需要知道哪些积木在同一堆里,故想到用并查集,而我们又需要知道每两块积木之间的关系,以待求某块积木下有多少块积木,于是想到按秩合并或带权并查集,并记录每一堆里有多少积木,我上面的做法倒是有一点按秩合并的影子,但。。我也不知道是什么诡异的算法,可能。。还有一点链式结构的影子???好吧怪不得分拿不满嘤嘤嘤(虽然说考场上要是能打出来只错两个点的程序我基本也就心满意足了)
1 #include<set> 2 #include<map> 3 #include<list> 4 #include<queue> 5 #include<stack> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9 #include<vector> 10 #include<bitset> 11 #include<memory> 12 #include<utility> 13 #include<cstdio> 14 #include<sstream> 15 #include<iostream> 16 #include<cstdlib> 17 #include<cstring> 18 #include<algorithm> 19 using namespace std; 20 21 int q; 22 int f[100005],d[100005],s[100005]; 23 24 int find(int z){//查找代表元并更新高度 25 if(f[z]==z)return z; 26 int t=find(f[z]); 27 d[z]+=d[f[z]]; 28 return f[z]=t; 29 } 30 31 int main() { 32 scanf("%d",&q); 33 for(int i=1;i<=q;i++){//初始化 34 f[i]=i,d[i]=0,s[i]=1; 35 } 36 for(int i=1;i<=q;++i){ 37 char zyy; 38 cin>>zyy; 39 if(zyy=='M'){//合并的情况 40 int z,y; 41 scanf("%d%d",&z,&y); 42 z=find(z); 43 y=find(y); 44 f[z]=y; 45 d[z]=s[y]; 46 s[y]+=s[z]; 47 } 48 else{//输出的情况 49 int zy; 50 scanf("%d",&zy); 51 find(zy); 52 printf("%d ",d[zy]); 53 } 54 } 55 return 0; 56 }
emmmm,真棒,坑不完了,7点47了,要上课去了,白白~~~