40pts RE or WA ? 码风良好注释充分求助
查看原帖
40pts RE or WA ? 码风良好注释充分求助
227728
冰糖鸽子TJ鸽子协会楼主2021/7/23 18:30

RT,RE 1,4,51,4,5

盲猜是某个答案WA了使得 ^=一下就RE了。

WA的话哪应该是某个地方的细节问题/脑阔疼

主席树部分和模板的代码对了一下,感觉最有可能错在LCA或者离散化了 (但是哪儿都错一点儿也不是不可能是不是

注释代码:


// Problem: P2633 Count on a tree
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2633
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define M 100005
#define mid ((L+R)/2)
int Fa[30][M],rrt,n,m,ans;
int a[M],lg[M],ff,p2[30],rt[M];
int b[M],fa[M],U,V,K,cntp,d[M];
//Fa[i][j]是j的第2^i级祖先,rrt是题目给出的树的根,n,m,ans都知道
//a是点的权值,b和下面的bh,id用来离散化,lg和p2是log2和pow2,ff用的时候有说,rt是每棵主席链的根
//fa是父亲,和Fa[0]差不多吧,UVK用来输入,cntp动态开点,d深度
vector<int>road[M];//存路径,链式前向星困难户
map<int,int>bh,id;//如上上
struct node
{int ls,rs,ll,rr,cnt;}t[M<<6];//主席树节点结构体
int lowbit(int x) {return x & -x;}//Lowbit,求LCA方便
int buildt(int L,int R)//建空树
{
	int res=++cntp;//动态KD
	t[res].ll=L,t[res].rr=R,t[res].cnt=t[res].ls=t[res].rs=0;//初始化
	if(L==R) return res;//到叶子返回 
	t[res].ls=buildt(L,mid),t[res].rs=buildt(mid+1,R);//往下建
	return res;
}
int Ins_up(int rta,int L,int R,int v)//建主席链
{
	int res=++cntp;//动态KD
	t[res]=t[rta],t[res].cnt++;//复制,值域中数的数量+1
	if(L==R) return res;//到叶子返回
	if(mid>=v) t[res].ls=Ins_up(t[rta].ls,L,mid,v);
	else t[res].rs=Ins_up(t[rta].rs,mid+1,R,v);
	//上面是选方向往下建
	return res;
}
void Dfs(int A,int B,int fat)
{
	d[A]=B,rt[A]=Ins_up(rt[fat],1,n,id[a[A]]);//深度记录,建链
	Fa[0][A]=fat;//Fa初始化
	for(int i=1;i<=lg[B];i++) Fa[i][A]=Fa[i-1][Fa[i-1][A]];//倍增LCA初始化
	for(int i=0;i<road[A].size();i++) Dfs(road[A][i],B+1,A);//Dfs下去
}
int LCA(int A,int B)//倍增求LCA
{
	int da=d[A],db=d[B],fft;//深度,fft随便起的当f看就行
	int dc=abs(da-db);//深度差
	if(db>da) swap(A,B),swap(da,db);//让da成为深的那个
	while(dc)//只要深度不一样就往上跳
	{
		fft=lowbit(dc),dc-=fft;
		A=Fa[lg[fft]][A];//往上跳
	}
	if(A==B) return A;//防止返回成fa[A];
	for(int i=lg[db]+1;i>=0;i--) if(Fa[i][A]!=Fa[i][B]) A=Fa[i][A],B=Fa[i][B];//不一样就可以跳
	return Fa[0][A];
}
int Query(int u,int v,int F,int FA,int k)
{
	if(t[u].ll==t[u].rr) return t[u].ll;//到叶子返回
	ff=t[t[u].ls].cnt+t[t[v].ls].cnt-t[t[F].ls].cnt-t[t[FA].ls].cnt;//下面省码量,就是四棵树差分完了的树的左儿子cnt
	if(ff>=k) return Query(t[u].ls,t[v].ls,t[F].ls,t[FA].ls,k); return Query(t[u].rs,t[v].rs,t[F].rs,t[FA].rs,k-ff);//选一个方向往下,如果往右就k-=ff
}
signed main()
{
	cin>>n>>m;for(int i=0;i<=25;i++) p2[i]=pow(2,i); for(int i=0;i<=n+2;i++) lg[i]=log2(i);//初始化
	for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i]; sort(b+1,b+1+n); for(int i=1;i<=n;i++) id[b[i]]=i,bh[i]=b[i];//离散化
	for(int i=1;i<n;i++) cin>>U>>V,road[U].push_back(V),fa[V]=U;//输入树
	rt[0]=buildt(1,n);//建空树
	for(int i=1;i<=n;i++) if(!fa[i]) rrt=i; Dfs(rrt,1,0);//找根(不确定1是不是一定是根),建主席树
	for(int i=1;i<=m;i++)
	{
		cin>>U>>V>>K,U^=ans;//强制在线
		ans=bh[Query(rt[U],rt[V],rt[LCA(U,V)],rt[fa[LCA(U,V)]],K)];//求答案,套bh
		cout<<ans<<endl;//输出
	}
	return 0;//无了
}
2021/7/23 18:30
加载中...