T1:
考虑当前位于
如果走,期望多的贡献是
所以
找不到代码了
T2:
考虑实际上就是两棵树两条边分别在另一棵树上包含另一条边
把第二棵树的边在第一棵树上差分后再在第二棵树上单点加链求和
差分一下子树加单点查
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define re register
#define pii pair<int,int>
#define fi first
#define se second
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
cs int N=1000005;
char xxx;
vector<int> e2[N];
vector<pii> e1[N];
int n;
namespace bit{
int tr[N];
#define lb(x) (x&(-x))
inline void upd(int p,int k){
for(;p<=n;p+=lb(p))tr[p]+=k;
}
inline void update(int l,int r,int k){
upd(l,k),upd(r+1,-k);
}
inline int query(int p){
int res=0;
for(;p;p-=lb(p))res+=tr[p];
return res;
}
#undef lb
}
using bit::update;
using bit::query;
int top[N],siz[N],son[N],fa[N],dep[N],in[N],out[N],idx[N],dfn;
int up[N],ans[N];
struct EEE{
int u,v,lca;
}E2[N];
vector<int> p[N],del[N];
void dfs1(int u){
siz[u]=1,son[u]=0;
for(int i=0;i<e1[u].size();i++){
int v=e1[u][i].fi;
if(v==fa[u])continue;
fa[v]=u,dep[v]=dep[u]+1;
up[v]=e1[u][i].se;
dfs1(v),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp,in[u]=++dfn;
if(son[u])dfs2(son[u],tp);
for(int i=0;i<e1[u].size();i++){
int v=e1[u][i].fi;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
out[u]=dfn;
}
void dfs3(int u){
siz[u]=1,son[u]=0;
for(int i=0;i<e2[u].size();i++){
int v=e2[u][i];
if(v==fa[u])continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs3(v),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs4(int u,int tp){
top[u]=tp,in[u]=++dfn;;
if(son[u])dfs4(son[u],tp);
for(int i=0;i<e2[u].size();i++){
int v=e2[u][i];
if(v==fa[u]||v==son[u])continue;
dfs4(v,v);
}
out[u]=dfn;
}
inline int Lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return dep[u]>dep[v]?v:u;
}
inline int ask(int u,int v){
return query(in[u])+query(in[v])-2*query(in[Lca(u,v)]);
}
void dfs5(int u,int f){
int pre=0;
if(u>1)pre=ask(u,f);
for(int i=0;i<e1[u].size();i++){
int v=e1[u][i].fi;
if(v==f)continue;
dfs5(v,u);
}
for(int i=0;i<p[u].size();i++){
int x=p[u][i];
update(in[x],out[x],1);
}
for(int i=0;i<del[u].size();i++){
int x=del[u][i];
update(in[x],out[x],-2);
}
ans[up[u]]=ask(u,f)-pre;
}
char yyy;
int main(){
int size=40<<20;//40M
//__asm__ ("movl %0, %%esp
"::"r"((char*)malloc(size)+size));//调试用这个
__asm__ ("movq %0,%%rsp
"::"r"((char*)malloc(size)+size));//提交用这个
//main函数代码
n=read();
for(re int i=1;i<n;i++){
int u=read(),v=read();
e1[u].pb(pii(v,i)),e1[v].pb(pii(u,i));
}
for(re int i=1,u,v;i<n;i++){
u=read(),v=read();
e2[u].pb(v),e2[v].pb(u);
E2[i].u=u,E2[i].v=v;
}
dfs1(1),dfs2(1,1);
for(re int i=1;i<n;i++)E2[i].lca=Lca(E2[i].u,E2[i].v);
dfn=0,dfs3(1);
dfs4(1,1);
for(re int i=1,u,v,lca;i<n;i++){
u=E2[i].u,v=E2[i].v,lca=E2[i].lca;
if(dep[u]<dep[v])swap(u,v);
p[u].pb(u),p[v].pb(u),del[lca].pb(u);
}
dfs5(1,0);
for(int i=1;i<n;i++)cout<<ans[i]<<" ";
exit(0);
}
T3:
在上类似重剖,找方案最多的儿子,预处理向下的倍增数组
这样每次跳必然方案数减半
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define re register
#define pii pair<int,int>
#define fi first
#define se second
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
int n,m;
cs int N=200005;
int down[N][21],cost[N][21];
vector<int> e[N],val[N],ss[N];
int f[N],son[N],in[N],rt;
cs int lim=1e9+2;
inline int add(int a,int b){
return min(lim,a+b);
}
void dfs(int u){
if(f[u])return;
int hv=0;
for(int &v:e[u]){
dfs(v);
if(f[v]>f[son[u]])son[u]=v,hv=f[u]+1;
f[u]=add(f[u],f[v]+1);
val[u].pb(f[u]);
}
down[u][0]=son[u],cost[u][0]=hv;
for(int i=1;i<19;i++)down[u][i]=down[down[u][i-1]][i-1],cost[u][i]=add(cost[u][i-1],cost[down[u][i-1]][i-1]);
}
int find(int u,int k){
if(!k)return u;
for(int i=18;~i;i--){
if(down[u][i]&&cost[u][i]<=k&&k<=cost[u][i]+f[down[u][i]])
return find(down[u][i],k-cost[u][i]);
}
int pos=lower_bound(val[u].bg(),val[u].end(),k)-val[u].bg();
if(!pos)return find(e[u][pos],k-1);
return find(e[u][pos],k-val[u][pos-1]-1);
}
int main(){
#ifdef Stargazer
freopen("lx.cpp","r",stdin);
// freopen("my.out","w",stdout);
#endif
n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
e[u].pb(v),in[v]++;
}
for(int i=1;i<=n;i++)if(!in[i])rt=i;
dfs(rt);
int q=read();
while(q--){
int u=read(),k=read();
if(k>f[u]){cout<<-1<<'
';}
else cout<<find(u,k)<<'
';
}
}