231016C T4 P9340 [JOISC 2023 Day3] Tourism
题外话#
-
此做法的主要思路来自 图老师,比较巧妙的转化!至少对于我来说,比洛谷题解区的题解都要简单!
-
被卡掉了,好伤心/ll(upd:图老师说 不会被卡,他坚信是我代码有问题/yun -
今天的饭好难吃/ng
#
题意#
给出一棵有
题解#
考虑将询问挂在右端点,然后离线下来扫描,每次将
然后这就特别简单了啊,染色部分可以像图老师场切做法那样分块,也可以像我一样偷懒用
还是放一下代码吧,虽然 T 了还没调过,但是不得不说这个做法用
#
注意到每次都是查询 Ask(k)-Ask(l-1)-dep[lca]
,其中 dep
是到根的距离(容斥一下即可发现,不细讲了),Assign
的时候顺带在树状数组上修改即可!
跑得飞快!最慢的点 0.5s!重铸
#
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define re register
const int N=1e5+113;
int n,m,k,idx,head[N],ans[N],c[N];
int id[N],son[N],fa[N],dep[N],siz[N],top[N];
int st[N][25],flog[N],fpow[25];
int tr[N];
struct edge{
int u,v,nxt;
}e[N<<1];
il void adde(int u,int v){
e[++idx]={u,v,head[u]};
head[u]=idx;
}
il void dfs1(int x,int father,int depth){
fa[x]=father,dep[x]=depth,siz[x]=1;
for(re int i=head[x];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa[x])continue;
dfs1(v,x,depth+1);
siz[x]+=siz[v];
if(siz[v]>siz[son[x]])son[x]=v;
}
}
il void dfs2(int x,int top_now){
top[x]=top_now,id[x]=++idx;
if(!son[x])return;
dfs2(son[x],top_now);
for(re int i=head[x];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa[x]||v==son[x])continue;
dfs2(v,v);
}
}
il int Lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
il void GetST(){
fpow[0]=1;
for(re int i=1;i<=20;i++)fpow[i]=fpow[i-1]<<1;
for(re int i=2;i<=k;i++)flog[i]=flog[i>>1]+1;
for(re int i=1;i<=k;i++)st[i][0]=c[i];
for(re int i=1;i<=flog[k];i++)
for(re int j=1;j+fpow[i]-1<=k;j++)
st[j][i]=Lca(st[j][i-1],st[j+fpow[i-1]][i-1]);
}
il int GetLca(int l,int r){
int len=flog[r-l+1];
return Lca(st[l][len],st[r-fpow[len]+1][len]);
}
il int lowbit(int x){
return x&(-x);
}
il void Add(int x,int y){
if(!x)return;
while(x<=k+1){
tr[x]+=y;
x+=lowbit(x);
}
}
il int Ask(int x){
int res=0;
while(x){
res+=tr[x];
x-=lowbit(x);
}
return res;
}
struct Chtholly{
int l,r;
mutable int val;
Chtholly(int l,int r=0,int val=0):l(l),r(r),val(val){}
il bool operator<(const Chtholly &a)const{
return l<a.l;
}
};
set<Chtholly>s;
#define It set<Chtholly>::iterator
il It Split(int pos){
It fnd=s.lower_bound(Chtholly(pos));
if(fnd!=s.end()&&fnd->l==pos)return fnd;
if((--fnd)->r<pos)return s.end();
int l=fnd->l,r=fnd->r,val=fnd->val;
s.erase(fnd);
s.insert(Chtholly(l,pos-1,val));
return s.insert(Chtholly(pos,r,val)).first;
}
il void Assign(int l,int r,int x){
It R=Split(r+1),L=Split(l);
for(re It i=L;i!=R;i++)
Add(i->val,-(i->r-i->l+1));
s.erase(L,R);
s.insert(Chtholly(l,r,x));
Add(x,r-l+1);
}
// il int GetAns(int l,int r,int x){
// It R=Split(r+1),L=Split(l);
// int res=0;
// for(re It i=L;i!=R;i++)
// if(i->val>=x)res+=i->r-i->l+1;
// return res;
// }
il void Assign_Path(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
Assign(id[top[x]],id[x],z);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
Assign(id[y],id[x],z);
}
il int GetAns(int x,int lca){
return Ask(k+1)-Ask(x-1)-dep[lca];
}
struct query{
int l,r,id;
}q[N];
il bool cmp(query x,query y){
return x.r<y.r;
}
il int read(){
re int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
int main(){
n=read(),k=read(),m=read();
for(re int i=1;i<n;i++){
int u=read(),v=read();
adde(u,v),adde(v,u);
}
idx=0;
dfs1(1,0,0);
dfs2(1,1);
for(re int i=1;i<=k;i++)c[i]=read();
GetST();
for(re int i=1;i<=m;i++)
q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+1+m,cmp);
int pos=0;
s.insert(Chtholly(1,n,1));
for(re int i=1;i<=m;i++){
int l=q[i].l,r=q[i].r;
int lca=GetLca(l,r);
while(pos<r)pos++,Assign_Path(1,c[pos],pos+1);
ans[q[i].id]=GetAns(q[i].l+1,lca);
}
for(re int i=1;i<=m;i++)cout<<ans[i]<<'\n';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)