[Noip 2016] 매일 달리기 (나무 사슬 분할)
#include
#define N 300005
using namespace std;
int n,m;
int hson[N],num[N],ans[N],first[N],top[N],dep[N],fa[N],siz[N],dfn=0,tot=0,cnt=0,rt[N*3];
struct Node{int l,r,sum;}T[N*30];
struct node{int v,next;}e[N<<1];
int s[N],t[N],w[N],lca[N];
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline int read(){
int ret=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();
return ret;
}
inline void dfs1(int p){
siz[p]=1,hson[p]=0;
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa[p])continue;
fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
inline void dfs2(int p,int tp){
top[p]=tp,num[p]=++dfn;
if(hson[p])dfs2(hson[p],tp);
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v!=hson[p]&&v!=fa[p])dfs2(v,v);
}
}
inline void update(int&p,int l,int r,int k,int v){
if(!p)p=++tot,T[p].l=T[p].r=T[p].sum=0;
T[p].sum+=v;
if(l==r)return;
int mid=l+r>>1;
if(k<=mid)update(T[p].l,l,mid,k,v);
else update(T[p].r,mid+1,r,k,v);
}
inline int query(int p,int l,int r,int ql,int qr){
if(!p)return 0;
if(ql<=l&&r<=qr)return T[p].sum;
int mid=l+r>>1;
if(qr<=mid)return query(T[p].l,l,mid,ql,qr);
if(ql>mid)return query(T[p].r,mid+1,r,ql,qr);
return query(T[p].l,l,mid,ql,mid)+query(T[p].r,mid+1,r,mid+1,qr);
}
inline int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]return dep[x]int main(){
n=read(),m=read();
for(int i=1;iint u=read(),v=read();
add(u,v),add(v,u);
}
for(int i=1;i<=n;++i)w[i]=read();
dfs1(1),dfs2(1,1);
for(int i=1;i<=m;++i){
s[i]=read(),t[i]=read();
lca[i]=LCA(s[i],t[i]);
if(dep[s[i]]-dep[lca[i]]==w[lca[i]])--ans[lca[i]];
update(rt[dep[s[i]]],1,n,num[s[i]],1);
if(fa[lca[i]])update(rt[dep[s[i]]],1,n,num[fa[lca[i]]],-1);
}
for(int i=1;i<=n;++i)ans[i]+=query(rt[w[i]+dep[i]],1,n,num[i],num[i]+siz[i]-1);
memset(rt,0,sizeof(rt)),tot=0;
for(int i=1;i<=m;++i){
update(rt[n*2+dep[s[i]]-2*dep[lca[i]]],1,n,num[t[i]],1);
if(fa[lca[i]])update(rt[n*2+dep[s[i]]-2*dep[lca[i]]],1,n,num[fa[lca[i]]],-1);
}
for(int i=1;i<=n;++i)ans[i]+=query(rt[w[i]-dep[i]+n*2],1,n,num[i],num[i]+siz[i]-1);
for(int i=1;i<=n;++i)cout<' ';
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.