树的统计count

来源:互联网 发布:删除旧的windows文件夹 编辑:程序博客网 时间:2024/05/29 13:34
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#define maxn 300000#define ls x<<1#define rs x<<1|1using namespace std;int n,head[maxn],tot=0,v[maxn],top[maxn],son[maxn],fa[maxn],de[maxn],w[maxn],z,tree1[maxn],tree2[maxn],sz[maxn];char s[20];struct eg{    int to;    int nxt;}b[maxn];void link(int x,int y){    b[++tot].nxt=head[x];    b[tot].to=y;    head[x]=tot;}void dfs1(int x,int f){    sz[x]=1,fa[x]=f;    for (int i=head[x];i!=-1;i=b[i].nxt)    {        int t=b[i].to;        if (t==f) continue;        de[t]=de[x]+1;        dfs1(t,x);        sz[x]+=sz[t];        if (son[x]==-1||sz[son[x]]<sz[t]) son[x]=t;    }}void dfs2(int x,int tp){    top[x]=tp,w[x]=++z;    if (son[x]!=-1) dfs2(son[x],tp);    else return ;    for (int i=head[x];i!=-1;i=b[i].nxt)    {        int t=b[i].to;        if (t!=fa[x]&&t!=son[x]) dfs2(t,t);    }}void build(int x,int l,int r){    tree2[x]=0,tree1[x]=-900000000;    if (l==r) return ;    int mid=(l+r)>>1;    build (ls,l,mid);    build (rs,mid+1,r);}void updata(int x,int l,int r,int d,int y){    if (l==r&&l==d)     {        tree1[x]=y;        tree2[x]=y;        return ;    }    int mid=(l+r)>>1;    if (d<=mid)updata(ls,l,mid,d,y);    else updata(rs,mid+1,r,d,y);    tree1[x]=max(tree1[ls],tree1[rs]);    tree2[x]=tree2[ls]+tree2[rs];}int qsum(int x,int l,int r,int ll,int rr){    if (ll==l&&r==rr) return tree2[x];    int mid=(l+r)>>1;    if (ll>mid) return qsum(rs,mid+1,r,ll,rr);    else if (rr<=mid) return qsum(ls,l,mid,ll,rr);    else return qsum(ls,l,mid,ll,mid)+qsum(rs,mid+1,r,mid+1,rr);}int qmax(int x,int l,int r,int ll,int rr){    if (ll==l&&r==rr) return tree1[x];    int mid=(l+r)>>1;    if (rr<=mid) return qmax(ls,l,mid,ll,rr);    else if (ll>mid) return qmax(rs,mid+1,r,ll,rr);    else return max(qmax(ls,l,mid,ll,mid),qmax(rs,mid+1,r,mid+1,rr));}int find(int x,int y,int flag){    if (flag==1)    {        int ans=-900000000;        int f1=top[x],f2=top[y];        while(f1!=f2)        {            if(de[f1]<de[f2]) swap(f1,f2),swap(x,y);            ans=max(ans,qmax(1,1,z,w[f1],w[x]));            x=fa[f1],f1=top[x];        }        if (de[x]>de[y]) swap(x,y);        return max(ans,qmax(1,1,z,w[x],w[y]));    }    if (flag==2)    {        int ans=0;        int f1=top[x],f2=top[y];        while (f1!=f2)        {            if(de[f1]<de[f2]) swap(f1,f2),swap(x,y);            ans+=qsum(1,1,z,w[f1],w[x]);            x=fa[f1],f1=top[x];        }        if (de[x]>de[y]) swap(x,y);        return ans+qsum(1,1,z,w[x],w[y]);    }}int main(){    memset(head, -1, sizeof(head));    memset(son, -1, sizeof(son));    scanf ("%d",&n);    for (int i=1;i<n;++i)    {        int x,y;        scanf ("%d%d",&x,&y);        link(x,y);        link(y,x);    }    for (int i=1;i<=n;++i)        scanf ("%d",&v[i]);    de[1]=1;    dfs1(1,0);    dfs2(1,1);    build(1,1,z);    for (int i=1;i<=n;++i) updata(1,1,z,w[i],v[i]);    int q;    scanf("%d",&q);    for (int i=1;i<=q;++i)    {        scanf ("%s",s);        int x,y;        scanf ("%d%d",&x,&y);        if (s[0]=='C')        updata(1,1,z,w[x],y);        if (s[1]=='M')        printf("%d\n",find(x,y,1));         if (s[1]=='S')        printf("%d\n",find(x,y,2));     }    return 0;}

嗯我知道打得很丑然而毕竟是第一个几乎全靠自己的树剖板子吧qaq
诶嘿嘿

1 0
原创粉丝点击