Description
给定一棵有根树(根节点为1),每个点都带有权值,对于点u,其权值设为a[u],其父亲为fa[i]。现有两个函数f1,f2,定义如下:
如果u=1,f1[u]=a[u],f2[u]=1
否则
如果f1[fa[u]]+1
Input
第一行为n。第二行为n个正整数,第i个数代表第i个点初始时的权值a[i]。接下来n-1行,每行两个整数u,v,代表u与v连有一条边。接下来一行为一个正整数Q。下面Q行,每一行格式为0 u val 或1 u。
Output
对于每种格式为1 u的询问,输出一行两个数,分别为f1[u],f2[u]
Sample Input
3
1 2 3
1 2
2 3
1
1 3
Sample Output
3 3
Data Constraint
对于40%的数据 n<=1000,Q<=1000
对于另外40%的数据 保证这棵树为一条链
对于100%的数据 n<=200000,Q<=200000
Solution
这道题确实很签到,因为实在是太好想了
题目给出的f1,f2函数不就是在求从根节点到某个结点的最大值以及最大值出现的次数吗
那么我们直接树剖再套上线段树就好了
表示对这道题的数据很不满意
一堆人打个水法 比我少一千bytes跑得还贼快
对了,用dfs会爆栈
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define L rt*2
#define R rt*2+1
using namespace std;
const int N=200005;
struct edge{
int l,r,x,s,id;
} tr[4*N];
int x,y,z,n,i,qq,tot,fl,w1,w2,k,kk,yy,al;
int f1[N],f2[N],a[N],fa[N],he[N],nx[2*N],b[2*N],top[N],h[N],q[N],s[N],seq[N],dfn[N],son[N];
int read(){
int sum=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();}
return sum;
}
void add(int x,int y){nx[++tot]=he[x];he[x]=tot;b[tot]=y;}
inline void update(int rt){
if (tr[L].x==tr[R].x) tr[rt].s=tr[L].s+tr[R].s,tr[rt].id=tr[L].id;
else if (tr[L].x>tr[R].x) tr[rt].s=tr[L].s,tr[rt].id=tr[L].id;
else tr[rt].s=tr[R].s,tr[rt].id=tr[R].id;
tr[rt].x=max(tr[L].x,tr[R].x);
}
inline void make(int rt,int l,int r){
tr[rt].l=l,tr[rt].r=r;
if (l==r){
tr[rt].x=a[seq[l]]-h[seq[l]];
tr[rt].s=1;
tr[rt].id=seq[l];
return;
}
int mid=(l+r)>>1;
make(L,l,mid);
make(R,mid+1,r);
update(rt);
}
inline void change(int rt,int x,int z){
if (tr[rt].l==tr[rt].r){
tr[rt].x+=z; return;}
int mid=(tr[rt].l+tr[rt].r)>>1;
if (x<=mid) change(L,x,z); else change(R,x,z);
update(rt);
}
void query(int rt,int l,int r){
if (tr[rt].l==l&&tr[rt].r==r){
if (tr[rt].x>k) {
k=tr[rt].x;
kk=tr[rt].s;
al=tr[rt].id;}
else if (tr[rt].x==k) kk+=tr[rt].s;
return;
}
int mid=(tr[rt].l+tr[rt].r)>>1;
if (r<=mid) query(L,l,r);
else if (l>mid) query(R,l,r);
else query(L,l,mid),query(R,mid+1,r);
}
void bfs(){
int l,r,i,j,t,res;
l=0,r=1,q[r]=1;
while (l<r){
x=q[++l];
for(i=he[x];i;i=nx[i]){
j=b[i];
if (j==fa[x]) continue;
fa[j]=x; h[j]=h[x]+1;
q[++r]=j;}
}
fo(i,1,n) top[i]=i,s[i]=1;
fa[1]=0;
fd(i,n,1) s[fa[q[i]]]+=s[q[i]];
dfn[1]=1; s[0]=0;
fo(i,1,n) {
x=q[i],t=0,res=dfn[x];
for(j=he[x];j;j=nx[j]) if (s[b[j]]>s[t]&&b[j]!=fa[x]) t=b[j];
if (t) son[x]=t,top[t]=top[x],dfn[t]=res+1,res+=s[t];
for(j=he[x];j;j=nx[j])
if (b[j]!=t&&b[j]!=fa[x]) dfn[b[j]]=res+1,res+=s[b[j]];}
fo(i,1,n) seq[dfn[i]]=i;
}
int main(){
freopen("3.in","r",stdin);
freopen("1.out","w",stdout);
n=read();
fo(i,1,n) a[i]=read();
fo(i,1,n-1) add(x=read(),y=read()),add(y,x);
fa[1]=0,h[1]=1;
bfs();
make(1,1,n);
qq=read();
while (qq){
qq--;
x=read();
if (x==1){
y=read(); yy=y;
k=-1234456789; kk=0; x=0;
while (y!=0){
query(1,dfn[top[y]],dfn[y]);
y=fa[top[y]];
}
printf("%d %d\n",h[yy]+a[al]-h[al],kk);
} else {
y=read(),z=read();
change(1,dfn[y],z-a[y]);
a[y]=z;
}
}
}