zoukankan      html  css  js  c++  java
  • dtoi2679「SDOI2016」游戏

    题意:

         Alice 和 Bob 在玩一个游戏。

         游戏在一棵有 $n$ 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 $123456789123456789$。
         有时,Alice 会选择一条从 $s$ 到 $t$ 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 $r$,若 $r$ 与 $s$ 的距离是 $mathrm{dis}$,那么Alice 在点 $r$ 上添加的数字是 $acdot mathrm{dis}+b$。

         有时,Bob 会选择一条从 $s$ 到 $t$ 的路径。他需要先从这条路径上选择一个点,再从那个点上选择一个数字。

         Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。

         Bob 需要你帮他找出他能够选择的最小的数字。

         $ n leq 100000 $,$ m leq 100000 $,$ left| a ight| leq 10000 $。

    题解:

         直观的感受题目在做什么,实际上就是相当于在一段路径上插入一个线段,再求最小值,比较容易意识到是树链剖分+线段树维护线段。

         由于建立线段树是用dfs序建立的,考虑在树上的某一段重链,随着距离变化 $1$,显然dfs序也会变化 $1$,当然dfs序不等于距离,但是是线性关系,所以显然可以以dfs序作为横坐标,然后用线段树维护线段。

         然而打完树剖线段树之后,一试样例,读入都错了,才意识到这题是有边权的...

         那怎么办?现在距离变化 $w$,dfs序才变化 $1$,如何解决?可以修改一下dfs序的求法,同一条重链中,相邻两个点的dfs序可以由原来的变化 $1$ 强行改为变化 $w$,不同重链中随意(可以保留原来的变化 $1$)。然后这样就能得到一个新的dfs序,所有的操作在他们上面做,当然线段取值也只能由他们产生。

         接下来具体说一下这题中如何用线段树来维护线段,首先线段树动态开点,然后更新的时候,先找到对应的区间,对于两条线段,首先先找到“至少在这个区间的一半以上区域”更为优秀的那条线段,然后将它放在这个节点上,接下来再将另外一个线段往两个儿子的某一个儿子传下去。查询由于是区间查询,不仅要查询对应节点及其子节点的最优值,还要考虑这些节点的所有祖先所造成的贡献,可以判断一下区间相交之类的关系然后将端点代入计算。

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<cstdlib>
    using namespace std;
    const long long INF=123456789123456789ll;
    int n,m,fa[22][100002],ct,cnt=1,dp[100002];
    long long dep[100002],tim=1,d[100002];
    typedef struct{
        int zlt,xzd,zjds,xzz;
        long long dfn;
    }P;
    typedef struct{
        int to,w;
    }PP;
    typedef struct{
        int ls,rs;
        long long minx,maxx,k,b,Min;
    }XDS;
    P p[100002];
    XDS xds[5000002];
    vector<PP>g[100002];
    void dfs1(int x,int y){
        p[x].zjds=1;fa[0][x]=y;dp[x]=dp[y]+1;
        int Max=0,maxn=-1,w=0;
        for (int i=0;i<g[x].size();i++)
        if (g[x][i].to!=y)
        {
            dep[g[x][i].to]=dep[x]+g[x][i].w;
            dfs1(g[x][i].to,x);p[x].zjds+=p[g[x][i].to].zjds;
            if (p[g[x][i].to].zjds>Max)
            {
                Max=p[g[x][i].to].zjds;maxn=g[x][i].to;w=g[x][i].w;
            }
        }
        p[x].xzd=maxn;p[x].xzz=w;
    }
    void dfs2(int x,int y){
        p[x].dfn=d[++ct]=tim;
        if (p[y].xzd==x)p[x].zlt=p[y].zlt;else p[x].zlt=x;
        if (p[x].xzd!=-1){tim+=p[x].xzz;dfs2(p[x].xzd,x);}
        for (int i=0;i<g[x].size();i++)
        if (g[x][i].to!=y && g[x][i].to!=p[x].xzd){tim++;dfs2(g[x][i].to,x);}
    }
    int lca(int x,int y){
        if (dp[x]<dp[y])swap(x,y);
        int k=dp[x]-dp[y];
        for (int i=0;i<=20;i++)
        if ((1<<i)&k)x=fa[i][x];
        if (x==y)return x;
        for (int i=20;i>=0;i--)
        if (fa[i][x]!=fa[i][y])
        {
            x=fa[i][x];y=fa[i][y];
        }
        return fa[0][x];
    }
    long long jiaodian(long long k1,long long b1,long long k2,long long b2){
        return (b2-b1)/(k1-k2);
    }
    void hb(int root,long long begin,long long end){
        if (begin==end)
        {
            xds[root].minx=xds[root].maxx=begin;
            if (xds[root].k==INF)xds[root].Min=INF;else xds[root].Min=xds[root].k*begin+xds[root].b;
        }
        else
        {
            xds[root].minx=min(xds[xds[root].ls].minx,xds[xds[root].rs].minx);
            xds[root].maxx=max(xds[xds[root].ls].maxx,xds[xds[root].rs].maxx);
            xds[root].Min=min(xds[xds[root].ls].Min,xds[xds[root].rs].Min);
            if (xds[root].k<INF)xds[root].Min=min(xds[root].Min,min(xds[root].k*xds[root].minx+xds[root].b,xds[root].k*xds[root].maxx+xds[root].b));
        }
    }
    void build(int root,long long begin,long long end,long long wz){
        if (begin==end){xds[root].minx=xds[root].maxx=begin;return;}
        long long mid=(begin+end)/2;
        if (wz<=mid)
        {
            if (!xds[root].ls)xds[root].ls=++cnt;
            build(xds[root].ls,begin,mid,wz);
        }
        else
        {
            if (!xds[root].rs)xds[root].rs=++cnt;
            build(xds[root].rs,mid+1,end,wz);
        }
        hb(root,begin,end);
    }
    void gx(int root,long long begin,long long end,long long k,long long b){
        if (!root)return;
        if (xds[root].k==INF)
        {
            xds[root].k=k;xds[root].b=b;
            hb(root,begin,end);
            return;
        }
        if (xds[root].k==k)
        {
            xds[root].b=min(xds[root].b,b);
            hb(root,begin,end);
            return;
        }
        if (begin==end)
        {
            if (k*begin+b<xds[root].k*begin+xds[root].b)
            {
                xds[root].k=k;xds[root].b=b;
            }
            hb(root,begin,end);
            return;
        }
        long long mid=(begin+end)/2,jd=jiaodian(xds[root].k,xds[root].b,k,b);
        if (xds[root].k<k){swap(xds[root].k,k);swap(xds[root].b,b);}
        if (jd<=mid)
        {
            swap(xds[root].k,k);swap(xds[root].b,b);
            gx(xds[root].ls,begin,mid,k,b);
        }
        else gx(xds[root].rs,mid+1,end,k,b);
        hb(root,begin,end);
    }
    void gengxin(int root,long long begin,long long end,long long begin2,long long end2,long long k,long long b){
        if (begin>end2 || end<begin2 || !root)return;
        if (begin>=begin2 && end<=end2)
        {
            gx(root,begin,end,k,b);return;
        }
        long long mid=(begin+end)/2;
        gengxin(xds[root].ls,begin,mid,begin2,end2,k,b);gengxin(xds[root].rs,mid+1,end,begin2,end2,k,b);
        hb(root,begin,end);
    }
    long long chaxun(int root,long long begin,long long end,long long begin2,long long end2){
        if (begin>end2 || end<begin2 || !root)return INF;
        if (begin>=begin2 && end<=end2)return xds[root].Min;
        long long mid=(begin+end)/2,a1=INF,a2=INF;
        if (begin2<=begin && xds[root].k<INF)a1=xds[root].k*xds[root].minx+xds[root].b;
        else if(xds[root].k<INF)a1=xds[root].k*begin2+xds[root].b;
        if (end2>=end && xds[root].k<INF)a2=xds[root].k*xds[root].maxx+xds[root].b;
        else if(xds[root].k<INF)a2=xds[root].k*end2+xds[root].b;
        return min(min(chaxun(xds[root].ls,begin,mid,begin2,end2),chaxun(xds[root].rs,mid+1,end,begin2,end2)),min(a1,a2));
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            PP aa;aa.to=v;aa.w=w;
            g[u].push_back(aa);
            aa.to=u;
            g[v].push_back(aa); 
        }
        dfs1(1,0);dfs2(1,0);
        for (int i=0;i<5000002;i++){xds[i].Min=xds[i].minx=xds[i].k=xds[i].b=INF;xds[i].maxx=-INF;}
        for (int i=1;i<=n;i++)build(1,1,tim,d[i]);
        for (int i=1;i<=20;i++)
        for (int j=1;j<=n;j++)
        fa[i][j]=fa[i-1][fa[i-1][j]];
        while(m--)
        {
            int op;
            scanf("%d",&op);
            if (op==1)
            {
                int u,v,a,b;
                scanf("%d%d%d%d",&u,&v,&a,&b);
                int lc=lca(u,v);long long de=dep[u],d1=dep[u]-dep[lc];
                while(dep[u]>=dep[lc] && u)
                {
                    int x,y=u;
                    if (dep[p[u].zlt]<dep[lc])x=lc;else x=p[u].zlt;
                    gengxin(1,1,tim,p[x].dfn,p[y].dfn,-a,b+(long long)a*(de-dep[x]+p[x].dfn));
                    u=fa[0][p[u].zlt];
                }
                while(dep[v]>=dep[lc] && v)
                {
                    int x,y=v;
                    if (dep[p[v].zlt]<dep[lc])x=lc;else x=p[v].zlt;
                    gengxin(1,1,tim,p[x].dfn,p[y].dfn,a,b+(long long)a*(d1+dep[x]-dep[lc]-p[x].dfn));
                    v=fa[0][p[v].zlt];
                }
            }
            else
            {
                int u,v;long long ans=INF;
                scanf("%d%d",&u,&v);
                int lc=lca(u,v);
                while(dep[u]>=dep[lc] && u)
                {
                    int x,y=u;
                    if (dep[p[u].zlt]<dep[lc])x=lc;else x=p[u].zlt;
                    ans=min(ans,chaxun(1,1,tim,p[x].dfn,p[y].dfn));
                    u=fa[0][p[u].zlt];
                }
                while(dep[v]>=dep[lc] && v)
                {
                    int x,y=v;
                    if (dep[p[v].zlt]<dep[lc])x=lc;else x=p[v].zlt;
                    ans=min(ans,chaxun(1,1,tim,p[x].dfn,p[y].dfn));
                    v=fa[0][p[v].zlt];
                }
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    洛谷 P2713:「罗马游戏」
    洛谷 P4014:「分配问题」
    「洛谷P1433」吃奶酪
    信号的频谱分析,加噪降噪处理
    javascript学习笔记
    IDA学习笔记
    inline内联函数
    api hook学习笔记
    java反射学习笔记
    android基于MBR的bootkit病毒学习笔记
  • 原文地址:https://www.cnblogs.com/1124828077ccj/p/14409755.html
Copyright © 2011-2022 走看看