这个代码在双指针更新之后发现下面的 assert (下有注释标出)会爆炸,怎么看也看不出来有 bug,在这里卡了两个小时了……
我知道没人会帮我调所以我想知道这个有没有可能是 UB 的现象(?
// Author: Minghan Ye
// Name: P5984 [PA2019] Podatki drogowe
// URL: https://www.luogu.com.cn/problem/P5984
// ML: 1GB
// TL: 7000ms
// Time: 24/04/24 14:02
#include<bits/stdc++.h>
using namespace std;
#ifdef DEBUG
#include "E:/OI/normal/templates/debug.h"
#else
#define dbg(...) (void)0
#define msg(...) (void)0
#endif
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second
const int N=25001,MOD=1e9+7;
typedef unsigned long long ull;
const ull bas1=0x549499,bas2=0x994945;
mt19937 rd(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int l,int r)
{
return uniform_int_distribution<int>(l,r)(rd);
}
struct info
{
ull hsh;
info *l,*r;
info():hsh(0){l=r=nullptr;}
}*root;
int n,K;
vector<PII> g[N];
#define edge(x) for(int I=0,y=g[x][0].fi,z=g[x][0].se;I<g[x].size();++I,y=g[x][I].fi,z=g[x][I].se)
#define mid ((l+r)>>1)
#define rmd (mid+1)
void pushup(info *cur)
{
cur->hsh=cur->l->hsh*bas1+cur->r->hsh*bas2;
}
info *build(int *arr,int l=1,int r=n)
{
info *cur=new info();
if(l==r)return cur->hsh=arr[l],cur;
cur->l=build(arr,l,mid);
cur->r=build(arr,rmd,r);
return pushup(cur),cur;
}
info *add(int P,info *tr,int l=1,int r=n)
{
info *cur=new info();
if(l==r)return cur->hsh=tr->hsh+1,cur;
if(P<=mid)cur->r=tr->r,cur->l=add(P,tr->l,l,mid);
else cur->l=tr->l,cur->r=add(P,tr->r,rmd,r);
return pushup(cur),cur;
}
bool cmp(info *t1,info *t2,bool f,int l=1,int r=n)//t1<t2?
{
if(l==r)return t1->hsh<t2->hsh||t1->hsh==t2->hsh&&f;
if(t1->r->hsh==t2->r->hsh)return cmp(t1->l,t2->l,f,l,mid);
return cmp(t1->r,t2->r,f,rmd,r);
}
bool cmp2(info *t1,info *t2,info *t3,bool f,int l=1,int r=n)//t1+t2<t3
{
if(l==r)return t1->hsh+t2->hsh<t3->hsh||t1->hsh+t2->hsh==t3->hsh&&f;
if(t1->r->hsh+t2->r->hsh==t3->r->hsh)return cmp2(t1->l,t2->l,t3->l,f,l,mid);
return cmp2(t1->r,t2->r,t3->r,f,rmd,r);
}
#undef mid
#undef rmd
bool f(int x,int y,int z,int p)
{
if(x>y)swap(x,y);
if(z>p)swap(z,p);
return x<z||x==z&&y<p;
}
bool f2(int x,int y,int z,int p)
{
if(x>y)swap(x,y);
if(z>p)swap(z,p);
return x<z||x==z&&y<=p;
}
struct vtx
{
int u,f;
info *tr;
vtx(int u,int f,info *t):u(u),f(f),tr(t){}
bool operator<(const vtx &rhs)const
{
return cmp(tr,rhs.tr,u<rhs.u);
}
};
int siz[N],mx[N];
bool vis[N];
VI ids;
void getsiz(int x,int fa)
{
ids.PB(x);
siz[x]=1,mx[x]=0;
edge(x)
if(y!=fa&&!vis[y])
getsiz(y,x),siz[x]+=siz[y],mx[x]=max(mx[x],siz[y]);
}
int cent(int rt)
{
ids.clear();
getsiz(rt,0);
for(int i:ids)
if(mx[i]<<1<=siz[rt]&&siz[rt]<=siz[i]<<1)
return i;
assert(0);
}
vector<vtx>sub[N];
void dfs(int x,int fa,int ad,int tr,int rt,info *ft)
{
info *cur=add(ad,ft);
sub[rt].PB(x,tr,cur);
edge(x)
if(y!=fa&&!vis[y])
dfs(y,x,z,tr,rt,cur);
}
void dfz(int x)
{
x=cent(x);
dbg(x);
vis[x]=1;
sub[x].PB(x,x,root);
edge(x)
if(!vis[y])
dfs(y,x,z,y,x,root);
sort(ALL(sub[x]));
edge(x)
if(!vis[y])dfz(y);
}
int ps[N],tot,cnt[N];
bool find(int x,int t,int fa)
{
if(x==t)return 1;
edge(x)
if(y!=fa)
{
ps[z]++;
if(find(y,t,x))return 1;
ps[z]--;
}
return 0;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(nullptr);
// int _;cin>>_;while(_--)
cin>>n>>K;
for(int i=1,u,v,w;i<n;i++)cin>>u>>v>>w,g[u].PB(v,w),g[v].PB(u,w);
root=build(ps);
dfz(1);
ps[n]=n;
int L=1,R=n*(n-1)/2,lu=0,lv=0,ru=0,rv=0;
info *pl=root,*pr=build(ps);
while(1)
{
int u,v,id=rnd(1,R-L+1);
for(int j=1;j<=n;j++)
{
tot=cnt[j]=0;
edge(j)cnt[y]=0;
for(auto itl=sub[j].end(),itr=sub[j].end(),it=sub[j].begin();;)
{
while(itl-1>it&&!cmp2(it->tr,(itl-1)->tr,pl,f2(it->u,(itl-1)->u,lu,lv)))
tot++,cnt[(--itl)->f]++;//这里的双指针
while(itr>itl&&!cmp2(it->tr,(itr-1)->tr,pr,f(it->u,(itr-1)->u,ru,rv)))tot--,cnt[(--itr)->f]--;
int ccnt=tot-cnt[it->f];
if(ccnt>=id)
{
for(auto its=itl;its<itr;its++)
if(its->f!=it->f&&!--id)
{
u=it->u,v=its->u;
goto Ok;
}
assert(0);
}
else id-=ccnt;
if(itl==++it)
{
if(itr==itl)break;
tot--,cnt[(itl++)->f]--;
}
for(auto its=itl;its!=sub[j].end();its++)//这里的 assertion failed
assert(!cmp2(it->tr,its->tr,pl,f2(it->u,its->u,lu,lv)));
}
}
assert(0);
Ok:fill(ps+1,ps+n+1,0);
assert(find(u,v,0));
info *cur=build(ps);
assert(cmp(cur,pr,0)&&cmp(pl,cur,0));
int rnk=1;
for(int j=1;j<=n;j++)
{
tot=sub[j].size(),cnt[j]=0;
edge(j)cnt[y]=0;
for(auto k:sub[j])cnt[k.f]++;
for(auto itl=sub[j].end(),it=sub[j].begin();;)
{
tot--,cnt[it->f]--;
while(itl-1>it&&!cmp2(it->tr,(itl-1)->tr,cur,f(it->u,(itl-1)->u,u,v)))tot--,cnt[(--itl)->f]--;
rnk+=tot-cnt[it->f];
if(itl==++it)break;
}
}
if(rnk==K)
{
int ans=0,pw=1;
for(int j=1;j<=n;j++)
ans=(ans+1ll*(pw=1ll*pw*n%MOD)*ps[j])%MOD;
cout<<ans;
break;
}
if(rnk<K)L=rnk+1,lu=u,lv=v,pl=cur;
else R=rnk-1,ru=u,rv=v,pr=cur;
}
return 0;
}