12.15
最后20分钟写个闲话
今天没啥,调一道题调了一晚上😅😅😅
学习了树链剖分的一部分
树的统计
线段树+树剖
据说是板子题(???)
先建图再打俩DFS把树建好,然后线段树维护区间 \(max\) 和 \(sum\) 就行了,最后用树剖找答案。
Code
#include <bits/stdc++.h>
const int N=1e5+5;
#define endl '\n'
using namespace std;
struct edge
{
int next,to;
}e[N<<1];
struct tree
{
int l,r;
int maxx,sum;
}t[4*N+2];
int rt,n,m,r,a[N],cnt,head[N],tot;
int f[N],deep[N],size[N],son[N],rk[N],top[N],id[N];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
cnt=0;
memset(son,-1,sizeof(son));
}
void add(int u,int v)
{
e[tot].to=v;
e[tot].next=head[u];
head[u]=tot++;
}
void dfs1(int u,int fa,int depth)
{
f[u]=fa;
deep[u]=depth;
size[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v==fa) continue;
dfs1(v,u,depth+1);//深度加1
size[u]+=size[v];//更新父size
if(size[v]>size[son[u]] || son[u]==-1)
son[u]=v;//选取size最大的作为重儿子
}
}
void dfs2(int u,int v)
{
top[u]=v;
id[u]=cnt++;
rk[id[u]]=u;
if(son[u]==-1)
return ;
dfs2(son[u],v);
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u] && v!=f[u])
dfs2(v,v);//一个点位于轻链底端,那么它的top必然是它本身
}
}
void push_up(int p)
{
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
}
void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
if(l==r)
{
t[p].maxx=t[p].sum=a[rk[l]];
return;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
push_up(p);
}
void change(int p,int k,int v)
{
if(k==t[p].l && k==t[p].r)
{
t[p].maxx=t[p].sum=v;
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(k<=mid) change(p*2,k,v);
else change(p*2+1,k,v);
push_up(p);
}
int find_sum(int p,int l,int r)
{
if(l==t[p].l && r==t[p].r)
return t[p].sum;
int mid=(t[p].l+t[p].r)>>1;
if(r<=mid) return find_sum(p*2,l,r);
else if(l>mid) return find_sum(p*2+1,l,r);
else return find_sum(p*2,l,mid)+find_sum(p*2+1,mid+1,r);
}
int true_find_sum(int u,int v)
{
int f1=top[u],f2=top[v];
int tmp=0;
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
tmp+=find_sum(1,id[f1],id[u]);
u=f[f1];
f1=top[u];
}
if(deep[u]>deep[v]) swap(u,v);
return tmp+find_sum(1,id[u],id[v]);
}
signed main()
{
int u,v;
char op[20];
while(scanf("%d",&n)==1)
{
init();
for(int i=1;i<n;++i)
{
cin>>u>>v;
add(u,v);
add(v,u);
}
for(int i=1;i<=n;++i)
cin>>a[i];
dfs1(1,0,0);
dfs2(1,1);
build(1,0,cnt-1);
cin>>m;
while(m--)
{
cin>>op>>u>>v;
if(op[0]=='C')
change(1,id[u],v);
else if(strcmp(op,"QMAX") == 0)
cout<<true_find_max(u,v)<<endl;
else cout<<true_find_sum(u,v)<<endl;
}
}
}
乐,今天信息奥赛理论上停上了,理由是“教练出差”,我寻思教练也没走光啊,飞飞不就在吗?结果今天飞飞果然在😓😓😓,那为啥停上了啊?但是大家不出意外的都来了😍😍😍,然后一起开银趴😍😍😍,看片5分钟卢关2小时😈😈😈
?今晚没啥抽象事,不写了。
shenshen 和 STA_Morlin 开银趴🤣🤣🤣,感觉大家都是♂同😍😍😍
舍了🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋🐍🐋