• [ZJOI2008]树的统计(树链刨分)


    很裸的一道树刨题,老规矩做一下dfs序然后线段树维护一下

    略有不同的是应该维护一下最大最小值

    这道题我没怎么刻意去卡常数,最慢的一个998ms很神奇吧

    放一下链接 

    #include<bits/stdc++.h>
    #define ls(x) x<<1
    #define rs(x) x<<1|1
    const int INF=-2146183647;
    using namespace std;
    const int N=1e6+6;
    int m,n,k,p,tot,cnt,res,root,inc;
    int son[N],size[N],id[N],sum[N<<2],maxx[N<<2],fa[N],head[N],dep[N],top[N],vt[N],v[N];
    struct egde
    {
        int nx,to;
    } e[N];
    void add_edge(int a,int b)
    {
        cnt++;e[cnt].to=b;e[cnt].nx=head[a];head[a]=cnt;
        cnt++;e[cnt].to=a;e[cnt].nx=head[b];head[b]=cnt;
    }
    void push_up(int p)
    {
        sum[p]=sum[ls(p)]+sum[rs(p)];
        maxx[p]=max(maxx[ls(p)],maxx[rs(p)]);
    }
    void build(int p,int l,int r)
    {
        if (l==r) 
        {
            sum[p]=vt[l];
            maxx[p]=vt[l];
            return;
        }
        int mid=(l+r)>>1;
        build(ls(p),l,mid);
        build(rs(p),mid+1,r);
        push_up(p);
    }
    void update(int p,int l,int r,int pos,int val)
    {
        if (l==r&&l==pos)
        {
            sum[p]=val;
            maxx[p]=val;
            return;
        }
        int mid=(l+r)>>1;
        if (pos<=mid) update(ls(p),l,mid,pos,val);
        if (pos>mid) update(rs(p),mid+1,r,pos,val);
        push_up(p);
    }
    void qx(int p,int l,int r,int nl,int nr)
    {
        if (nl<=l&&r<=nr) 
        {
            res=max(res,maxx[p]);
            return;
        }
        int mid=(l+r)>>1;
        if (nl<=mid) qx(ls(p),l,mid,nl,nr);
        if (nr>mid) qx(rs(p),mid+1,r,nl,nr);
    }
    void query(int p,int l,int r,int xl,int xr)
    {
        if (xl<=l&&r<=xr) 
        {
            res+=sum[p];
            return;
        }
        int mid=(l+r)>>1;
        if (xl<=mid) query(ls(p),l,mid,xl,xr);
        if (xr>mid) query(rs(p),mid+1,r,xl,xr);
    }
    void dfs1(int x,int f,int deep)
    {
        fa[x]=f;
        dep[x]=deep;
        size[x]=1;
        int maxson=-1;
        for (int i=head[x];i;i=e[i].nx)
        {
            int y=e[i].to;
            if (y==fa[x]) continue;
            dfs1(y,x,deep+1);
            size[x]+=size[y];
            if (size[y]>maxson) {maxson=size[y];son[x]=y;}
        }
    }
    void dfs2(int x,int topf)
    {
        id[x]=++tot;
        vt[tot]=v[x];
        top[x]=topf;
        if (!son[x]) return;
        dfs2(son[x],topf);
        for (int i=head[x];i;i=e[i].nx)
        {
            int y=e[i].to;
            if (y==fa[x]||y==son[x]) continue;
            dfs2(y,y);
        }
    }
    int qrange(int x,int y)
    {
        int ans=0;
        while (top[x]!=top[y])
        {
            res=0;
            if (dep[top[x]]<dep[top[y]]) swap(x,y);
            query(1,1,n,id[top[x]],id[x]);
            ans+=res;
            x=fa[top[x]];
        }
        if (dep[x]>dep[y]) swap(x,y);
        res=0;
        query(1,1,n,id[x],id[y]);
        ans+=res;
        return ans;
    }
    int qmax(int x,int y)
    {
        int ans=INF;
        while (top[x]!=top[y])
        {
            res=INF;
            if (dep[top[x]]<dep[top[y]]) swap(x,y);
            qx(1,1,n,id[top[x]],id[x]);
            ans=max(ans,res);
            x=fa[top[x]];
        }
        if (dep[x]>dep[y]) swap(x,y);
        res=INF;
        qx(1,1,n,id[x],id[y]);
        ans=max(ans,res);
        return ans;
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add_edge(x,y);
        }
        for (int i=1;i<=n;i++) scanf("%d",&v[i]);
        root=1;
        dfs1(root,0,1);
        dfs2(root,root);
        build(1,1,n);
        scanf("%d",&m);
        string c;
        for (int i=1;i<=m;i++)
        {
            cin>>c;int x,y;
            scanf("%d%d",&x,&y);
            if (c=="QMAX") {printf("%d
    ",qmax(x,y));}
            if (c=="QSUM") {printf("%d
    ",qrange(x,y));}
            if (c=="CHANGE") {update(1,1,n,id[x],y);}
        }
        return 0;
    }
    慢即是快,细则是能,于小处铸迤逦
  • 相关阅读:
    SQL SERVER2005中将普通表修改为分区表
    手把手教你建立SQL数据库的表分区
    捕获input 文本框内容改变的事件(onchange,onblur,onPropertyChange比较)
    sql语句求排名
    带输出参数的插入语句
    js Base64.encode(str)_decode(str).html
    jquery.base64.js(完美解决中文乱码) 免费版
    sql数据库如何获取某个字段里的最大值?
    C#里封装 继承 多态
    C#中的属性get和set()方法
  • 原文地址:https://www.cnblogs.com/Hale522520/p/10620638.html
Copyright © 2020-2023  润新知