树链剖分
晚上神志不清的时候写的,头晕眼花si初值忘记赋了,导致变成了随机连剖分(丢人.....)
/**************************************************************
Problem: 3631
User: syh0313
Language: C++
Result: Accepted
Time:1828 ms
Memory:61640 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using namespace std;
const int maxn=400010;
int n,ord[maxn],topt,to[maxn<<1],st[maxn<<1],nt[maxn<<1],root,cnt;
int fa[maxn],rem[maxn],si[maxn],dep[maxn];
int dfn[maxn],line[maxn],dfn_num,top[maxn];
long long ans[maxn];
bool f[maxn];
struct da{int lc,rc;long long tag;}a[maxn<<2];
void add(int x,int y)
{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}
void dfs1(int x,int de)
{
f[x]=1; dep[x]=de; si[x]=1; int p=st[x],ma=0;
while (p)
{
if (!f[to[p]])
{
dfs1(to[p],de+1);
fa[to[p]]=x; si[x]+=si[to[p]];
if (si[to[p]]>ma) {ma=si[to[p]]; rem[x]=to[p];}
}
p=nt[p];
}
}
void dfs2(int x)
{
f[x]=1; if (rem[fa[x]]==x) top[x]=top[fa[x]];else top[x]=x;
dfn[x]=++dfn_num; line[dfn_num]=x;
if (rem[x]) dfs2(rem[x]);
int p=st[x];
while (p)
{
if (!f[to[p]]) dfs2(to[p]);
p=nt[p];
}
}
/*void build_tree(int &n,int l,int r)
{
n=++cnt; if (l==r) return;
int mid=(l+r)>>1;
build_tree(lch,l,mid); build_tree(rch,mid+1,r);
}
*/
void tree_add(int &n,int L,int R,int l,int r)
{
if (!n) n=++cnt;
if (L==l && R==r) {a[n].tag++; return;}
int mid=(L+R)>>1;
if (r<=mid) tree_add(lch,L,mid,l,r);
else if (l>=mid+1) tree_add(rch,mid+1,R,l,r);
else tree_add(lch,L,mid,l,mid),tree_add(rch,mid+1,R,mid+1,r);
}
void tadd(int x,int y)
{
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
tree_add(root,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if (dfn[x]>dfn[y]) swap(x,y);
tree_add(root,1,n,dfn[x],dfn[y]);
}
void qury(int &n,int l,int r,long long k)
{
if (!n) topt++;
if (l==r) {ans[line[l]]=k; return;}
int mid=(l+r)>>1;
qury(lch,l,mid,k+a[lch].tag);
qury(rch,mid+1,r,k+a[rch].tag);
}
int read()
{
int xx=0,ff=1; char c=getchar();
while (c<'0' || c>'9') {if (c=='-') ff=-1; c=getchar();}
while (c>='0' && c<='9') {xx=(xx<<1)+(xx<<3)+c-'0'; c=getchar();}
return xx*ff;
}
int main()
{
//freopen("1.in","r",stdin);
n=read(); for (int i=1;i<=n;i++) ord[i]=read();
for (int i=1;i<n;i++)
{
int xx,yy; xx=read(); yy=read();
add(xx,yy); add(yy,xx);
}
dfs1(1,1); memset(f,0,sizeof f); dfs2(1);
//build_tree(root,1,n);
for (int i=1;i<=n-1;i++) tadd(ord[i],ord[i+1]);
qury(root,1,n,a[root].tag);
for (int i=2;i<=n;i++) ans[ord[i]]--;
for (int i=1;i<=n;i++) printf("%lld\n",ans[i]);
return 0;
}

566

被折叠的 条评论
为什么被折叠?



