P5838 [USACO19DEC]Milk Visits G
看似要用LCA来写,但是并不需要
考虑树剖的重要性质,重链上时间戳连续,那么就可以按照时间戳的顺序建主席树,无脑的查就行了
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define re int
#define void inline void
#define eps 1e-5
//#define mod 1e9+7
//#define ls(p) p<<1
//#define rs(p) p<<1|1
//#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
#define fi first
#define se second
#define unordered_map map
//#define __int128 long long
using namespace std;
using namespace __gnu_pbds;
const int M=1e5+5;
const int mod=1e9;
const int N=2e5+5;
int n,m,a[N];
int s[N],tp;
namespace HJT
{
#define ls(p) e[p].l
#define rs(p) e[p].r
struct node
{
int l,r,sum;
}e[N*40];
int rt[N],tot;
void insert(int &p,int pre,int l,int r,int pos)
{
p=++tot;
e[p]=e[pre];
e[p].sum++;
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) insert(ls(p),ls(pre),l,mid,pos);
else insert(rs(p),rs(pre),mid+1,r,pos);
}
int ask(int L,int R,int l,int r,int pos)
{
if(l==r) return e[R].sum-e[L].sum;
int mid=(l+r)>>1;
if(pos<=mid) return ask(ls(L),ls(R),l,mid,pos);
return ask(rs(L),rs(R),mid+1,r,pos);
}
}
namespace GP
{
using namespace HJT;
struct nod
{
int ver,next;
}e[N];
int tot,head[N];
int num,sz[N],top[N],fa[N],son[N],dfn[N],w[N],d[N];
void add(int x,int y)
{
e[++tot].ver=y;
e[tot].next=head[x];
head[x]=tot;
}
void addedge(int x,int y)
{
add(x,y);add(y,x);
}
void dfs1(int x,int pre)
{
sz[x]=1,fa[x]=pre,d[x]=d[pre]+1;
int ma=-1;
for(re i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
if(y==pre) continue;
dfs1(y,x);
sz[x]+=sz[y];
if(ma<sz[y]) ma=sz[y],son[x]=y;
}
}
void dfs2(int x,int pre)
{
top[x]=pre;dfn[x]=++num;
w[num]=a[x];
if(!son[x]) return;
dfs2(son[x],pre);
for(re i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
if(y==son[x]||y==fa[x]) continue;
dfs2(y,y);
}
}
void bulid()
{
for(re i=1;i<=n;i++) insert(rt[i],rt[i-1],1,n,w[i]);
}
void query(int x,int y,int op)
{
int z=0,ans=0;
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]]) swap(x,y);
ans=ask(rt[dfn[top[x]]-1],rt[dfn[x]],1,n,op);
if(ans) z=1;
x=fa[top[x]];
}
if(d[x]>d[y]) swap(x,y);
ans=ask(rt[dfn[x]-1],rt[dfn[y]],1,n,op);
if(ans) z=1;
s[++tp]=z;
}
}
void solve()
{
cin>>n>>m;
for(re i=1;i<=n;i++) scanf("%d",&a[i]);
for(re i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
GP::addedge(x,y);
}
GP::dfs1(1,1);GP::dfs2(1,1);
GP::bulid();
for(re i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
GP::query(x,y,z);
}
for(re i=1;i<=m;i++) printf("%d",s[i]);puts("");
}
signed main()
{
// fflush(stdout);
// srand(102321547);
// freopen("D.in", "r", stdin);
// freopen("D2.out", "w", stdout);
// freopen("9.out", "w", stdout);
int T=1;
// cin>>T;
for(re index=1;index<=T;index++)
{
// printf("Case #%d:\n",index);
solve();
// puts("");
}
return 0;
}
/*
1 4
3 4
15 38 45 52 59 36
*/