一个玄学问题

P2619 [国家集训队] Tree I

%%%
by huhao @ 2019-09-10 18:13:00


这是我50分代码: ```cpp #include<bits/stdc++.h> using namespace std; inline int read(){ int a=0;char c=getchar(); while(c>'9'||c<'0')c=getchar(); while('0'<=c&&c<='9'){ a=a*10+c-48; c=getchar(); } return a; } #define MN 200005 struct data{ int a,b,c; bool friend operator<(data a,data b){ return a.c<b.c; } }w[2][MN]; int anss,tmp[MN]; int n,m,F,V,Fa[MN],cnt[2]; data Get(int l,int r){ if(l>cnt[0])return w[1][r]; if(r>cnt[1])return w[0][l]; if(w[0][l]<w[1][r]) return w[0][l]; return w[1][r]; } int Find(int a){ if(Fa[a]==a)return a; return Fa[a]=Find(Fa[a]); } signed main(){ n=read();m=read(); int ned=read(); int a,b,c; for(int i=1;i<=m;++i){ a=read()+1;b=read()+1;c=read();int x=read()^1; w[x][++cnt[x]].a=a;w[x][cnt[x]].b=b;w[x][cnt[x]].c=c; } sort(w[0]+1,w[0]+1+cnt[0]); sort(w[1]+1,w[1]+1+cnt[1]); int l=-105,r=105; int sum; while(l+1<r){ int mid=(l+r)>>1; sum=0; for(int i=1;i<=cnt[1];++i) tmp[i]=w[1][i].c,w[1][i].c+=mid; for(int i=1;i<=n;++i)Fa[i]=i; int Cnt=0,CNT1=0,L=1,R=1; while(Cnt<n&&(L<=cnt[0]||R<=cnt[1])){ data x=Get(L,R); int fa=Find(x.a),fb=Find(x.b); if(fa!=fb)Fa[fa]=fb,Cnt++,sum+=x.c; if(x.c==w[1][R].c) { R++; if(fa!=fb)CNT1++; } else L++; } if(CNT1>=ned) l=mid; else r=mid; for(int i=1;i<=cnt[1];++i)w[1][i].c=tmp[i]; } anss=sum-ned*l; printf("%d",anss); return 0; } ``` 这是100分: ```cpp #include<bits/stdc++.h> using namespace std; inline int read(){ int a=0;char c=getchar(); while(c>'9'||c<'0')c=getchar(); while('0'<=c&&c<='9'){ a=a*10+c-48; c=getchar(); } return a; } #define MN 200005 struct data{ int a,b,c; bool friend operator<(data a,data b){ return a.c<b.c; } }w[2][MN]; int anss,tmp[MN]; int n,m,F,V,Fa[MN],cnt[2]; data Get(int l,int r){ if(l>cnt[0])return w[1][r]; if(r>cnt[1])return w[0][l]; if(w[0][l]<w[1][r]) return w[0][l]; return w[1][r]; } int Find(int a){ if(Fa[a]==a)return a; return Fa[a]=Find(Fa[a]); } signed main(){ n=read();m=read(); int ned=read(); int a,b,c; for(int i=1;i<=m;++i){ a=read()+1;b=read()+1;c=read();int x=read()^1; w[x][++cnt[x]].a=a;w[x][cnt[x]].b=b;w[x][cnt[x]].c=c; } sort(w[0]+1,w[0]+1+cnt[0]); sort(w[1]+1,w[1]+1+cnt[1]); int l=-105,r=105; int sum; while(l+1<r){ int mid=(l+r)>>1; sum=0; for(int i=1;i<=cnt[1];++i) tmp[i]=w[1][i].c,w[1][i].c+=mid; for(int i=1;i<=n;++i)Fa[i]=i; int Cnt=0,CNT1=0,L=1,R=1; while(Cnt<n&&(L<=cnt[0]||R<=cnt[1])){ data x=Get(L,R); int fa=Find(x.a),fb=Find(x.b); if(fa!=fb)Fa[fa]=fb,Cnt++,sum+=x.c; if(x.c==w[1][R].c) { R++; if(fa!=fb)CNT1++; } else L++; } if(CNT1>=ned) { l=mid; anss=sum-ned*l; } else r=mid; for(int i=1;i<=cnt[1];++i)w[1][i].c=tmp[i]; } printf("%d",anss); return 0; } ``` 它们只有个地方不一样: `anss=sum-ned*l;` 第一份最后统计,第二份每次都统计 求大佬解释一下,感激不尽 另外小蒟蒻的二分比较奇葩,请注意一下
by skydogli @ 2019-09-10 18:13:22


@[skydogli](/space/show?uid=7480) 因为统计是建立在CNT1>=ned的基础上的
by Kubic @ 2019-09-10 18:15:38


@[Kubic](/space/show?uid=119621) 谢谢巨佬,但应该不是这个问题,我的l只会在这里改变,然后我再交了一次记录l是否改变,显示都是改变的,那么答案也应该没错才对?
by skydogli @ 2019-09-10 18:20:33


@[skydogli](/space/show?uid=7480) 1、我不是巨佬 2、请问您如何通过提交代码知道每次都改变了?
by Kubic @ 2019-09-10 18:23:39


@[Kubic](/space/show?uid=119621) l改变时vis=1,如果vis=0说明从始至终l值为改变
by skydogli @ 2019-09-10 18:27:30



by skydogli @ 2019-09-10 18:28:20


@[skydogli](/space/show?uid=7480) 但是如果在外面的话,sum和ned可能已经改变了,就与最后一个满足条件的不同了
by Kubic @ 2019-09-10 18:31:29


@[Kubic](/space/show?uid=119621) 哦!谢谢大佬!!!
by skydogli @ 2019-09-10 18:46:03


Orz
by longlongzhu123 @ 2019-09-10 19:00:30


|