最近公共祖先(lca)
题目描述
给定一颗有n个结点的有根树,结点编号为1∼n,其中根结点为1号结点。每个结点都对应着一种颜色(黑/白)和一个固定的权值,初始时所有结点的颜色都为白色。现在你需要实现以下两种操作:
∙ Modify v∙ 将结点v的颜色修改成黑色;
∙ Query v∙ 找到一个黑色结点u,使得结点u和v的最近公共祖先z对应的权值尽可能的大,输出结点z的权值。如果此时树中不存在黑色结点,输出−1。
输入
第一行为两个正整数n和m,分别表示树中的结点数以及操作总数目。
第二行为nn个正整数w1,w2,…,wn(wi≤109),分别表示这nn个结点对应的权值。
接下来n−1行,每行两个正整数ai,bi表示结点ai和bi结点之间有一条边相连。
接下来m行,每行由一个字符串str和一个正整数v组成,分别表示操作类型以及操作对应结点的编号。
输出
对于每个询问操作,每行输出一个整数,对应着这个询问的答案。
样例输入
7 7
4 3 5 7 6 5 2
1 4
2 1
7 5
6 2
2 5
3 4
Query 1
Modify 2
Modify 4
Query 3
Modify 2
Modify 5
Query 6
样例输出
-1
7
4
提示
对于10%10%的数据:n≤100,m≤200
对于20%20%的数据:n≤3000,m≤3000
对于另外20%20%的数据:对于编号为ii的结点,其父亲结点编号在[1,i−1]内均匀随机
对于另外20%20%的数据:保证Query操作在所有Modify操作完成之后
对于100%100%的数据:n≤105,m≤2×105
来源
我的方法太傻逼,
不建议参考!!!
首先你发现,成为答案的点,一定在一个轻链顶端。
于是我对于Modify,把它到根的路径加1 并把轻链的father的值加进线段树的Max里
因为这些点有望成为lca。
对于Query
假设我之前的链权值为111... (注意不是Max)
然后跳了轻链后变成大于1的数,
也就是说,有一个(多个)不同子树的染黑节点经过了这个lca
那么这个lca就是合法的
接着还要询问Max (相当于另一个染黑节点跳上了这条链)
码量大,细节多
调了一早上,成绩 :10 分
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 100005
using namespace std;
int n,m,head[maxn],son[maxn],size[maxn],deep[maxn],fa[maxn],top[maxn];
int w[maxn],dfn[maxn],dy[maxn],sc,li,ri,tot,t1,t2,t,a,flag;
int root,ans,la,mla;
char cha[8];
struct node{
int v,nex;
}e[maxn*2];
struct no{
int l,r,ma,y,x,bj;
}tree[maxn*4];
void lj(int t1,int t2){
tot++;e[tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
}
void dfs1(int k,int fath){
fa[k]=fath;deep[k]=deep[fath]+1;
int gp=-1,sz=0;
for(int i=head[k];i;i=e[i].nex){
if(e[i].v!=fath){
dfs1(e[i].v,k);
if(gp==-1)gp=e[i].v;
if(size[e[i].v]>size[gp])gp=e[i].v;
sz+=size[e[i].v];
}
}
son[k]=gp,size[k]=sz+1;
}
void dfs2(int k){
dfn[k]=++sc;dy[sc]=k;
if(son[k]!=-1)top[son[k]]=top[k],dfs2(son[k]);
for(int i=head[k];i;i=e[i].nex){
if(e[i].v!=fa[k]&&e[i].v!=son[k]){
top[e[i].v]=e[i].v;
dfs2(e[i].v);
}
}
}
void wh(int k){
tree[k].x=max(tree[k*2].x,tree[k*2+1].x);
tree[k].y=min(tree[k*2].y,tree[k*2+1].y);
tree[k].ma=max(tree[k*2].ma,tree[k*2+1].ma);
}
void build(int k,int L,int R){
tree[k].l=L,tree[k].r=R;
if(L==R)return;
int mid=L+R>>1;
build(k*2,L,mid);build(k*2+1,mid+1,R);
wh(k);
}
void down(int k){
if(tree[k].bj>0){
t=tree[k].bj;
tree[k*2].x+=t;tree[k*2+1].x+=t;
tree[k*2].y+=t;tree[k*2+1].y+=t;
tree[k*2].bj+=t;tree[k*2+1].bj+=t;
tree[k].bj=0;
}
}
void ch(int k,int pl){
if(tree[k].l==tree[k].r){
tree[k].ma=w[dy[tree[k].l]];
return;
}
down(k);
int mid=tree[k].l+tree[k].r>>1;
if(pl<=mid)ch(k*2,pl);
else ch(k*2+1,pl);
wh(k);
}
void jia(int k){
if(tree[k].l>=li&&tree[k].r<=ri){
tree[k].x++;tree[k].y++;tree[k].bj++;
//cout<<tree[k].l<<' '<<tree[k].r<<' '<<tree[k].x<<' '<<tree[k].y<<endl;
return;
}
down(k);
int mid=tree[k].l+tree[k].r>>1;
if(li<=mid)jia(k*2);
if(ri>mid)jia(k*2+1);
wh(k);
}
void ask_p(int k,int pl){
if(tree[k].l==tree[k].r){
if(tree[k].x>la){
ans=max(ans,w[dy[tree[k].l]]);
la=tree[k].x;
}
return;
}
down(k);
int mid=tree[k].l+tree[k].r>>1;
if(pl<=mid)ask_p(k*2,pl);
else ask_p(k*2+1,pl);
}
void ask_l(int k){
if(tree[k].l>=li&&tree[k].r<=ri){
//cout<<"aa "<<tree[k].l<<' '<<tree[k].r<<endl;
if(tree[k].x<=la)return;
if(tree[k].y<=la){
//cout<<la<<' '<<tree[k].x<<' '<<tree[k].y<<endl
down(k);
int ls=k*2,rs=k*2+1;
if(tree[rs].x>la){
ans=max(ans,tree[ls].ma);mla=max(mla,tree[ls].x);
ask_l(k*2+1);
}
else {
if(tree[ls].x<=la)return;
//down(k);
ask_l(k*2);
}
return;
}
ans=max(ans,tree[k].ma);mla=max(mla,tree[k].x);
return;
}
down(k);
int mid=tree[k].l+tree[k].r>>1;
if(li<=mid)ask_l(k*2);
if(ri>mid)ask_l(k*2+1);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
for(int i=1;i<n;i++){
scanf("%d%d",&t1,&t2);
lj(t1,t2);lj(t2,t1);
}
dfs1(1,0);top[1]=1;dfs2(1);root=1;
build(1,1,n);
//for(int i=1;i<=n;i++)cout<<dfn[i]<<' ';cout<<endl;
for(int i=1;i<=m;i++){
scanf("%s %d",cha,&a);
if(cha[0]=='M'){
flag=1;
t1=top[a];
while(t1!=root){
ch(1,dfn[a]);
li=dfn[t1],ri=dfn[a];
jia(1);
a=fa[t1];t1=top[a];
}//cout<<"aaa "<<a<<' '<<dfn[a]<<endl;;
ch(1,dfn[a]);
li=dfn[root],ri=dfn[a];
jia(1);
}
if(cha[0]=='Q'){
if(!flag){puts("-1");continue;}
t1=top[a];ans=0;la=0;
while(t1!=root){
ask_p(1,dfn[a]);
//cout<<"aa "<<la<<endl;
li=dfn[t1],ri=dfn[a];
mla=0;/////
ask_l(1);//cout<<dfn[a]<<' '<<ans<<endl;
la=max(la,mla);//cout<<mla<<endl;
a=fa[t1],t1=top[a];
}
//cout<<"aaa "<<la<<endl;
ask_p(1,dfn[a]);
//cout<<dfn[a]<<' '<<ans<<endl;
li=dfn[root],ri=dfn[a];
mla=0;ask_l(1);la=max(la,mla);
printf("%d
",ans);
}
}
return 0;
}