12.15

发布时间 2023-12-15 21:50:57作者: HS_xh

最后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 开银趴???,感觉大家都是♂同???

舍了????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

USAO

一晚上真正的成果(不是)

image