• 洛谷 P1505 [国家集训队]旅游 解题报告


    P1505 [国家集训队]旅游

    题目描述

    ( t{Ray}) 乐忠于旅游,这次他来到了(T)城。(T)城是一个水上城市,一共有 (N) 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,(T) 城的任意两个景点之间有且只有一条路径。换句话说, (T) 城中只有 (N − 1) 座桥。

    ( t{Ray}) 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度(w),也就是说,( t{Ray}) 经过这座桥会增加(w)的愉悦度,这或许是正的也可能是负的。有时,( t{Ray}) 看待同一座桥的心情也会发生改变。

    现在,( t{Ray}) 想让你帮他计算从(u)景点到(v)景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。

    输入输出格式

    输入格式:

    输入的第一行包含一个整数(N),表示(T)城中的景点个数。景点编号为 (0dots N − 1)

    接下来 (N − 1) 行,每行三个整数(u)(v)(w),表示有一条 (u)(v),使 ( t{Ray}) 愉悦度增加 (w) 的桥。桥的编号为(1dots N − 1)(|w| le 1000)。 输入的第 (N + 1) 行包含一个整数(M),表示 ( t{Ray}) 的操作数目。

    接下来有 (M) 行,每行描述了一个操作,操作有如下五种形式:

    • C i w,表示( t{Ray})对于经过第 (i) 座桥的愉悦度变成了 (w)

    • N u v,表示( t{Ray}) 对于经过景点 (u)(v) 的路径上的每一座桥的愉悦度都变成原来的相反数。

    • SUM u v,表示询问从景点 (u)(v) 所获得的总愉悦度。

    • MAX u v,表示询问从景点 (u)(v) 的路径上的所有桥中某一座桥所提供的最大愉悦度。

    • MIN u v,表示询问从景点 (u)(v) 的路径上的所有桥中某一座桥所提供的最小愉悦度。

    测试数据保证,任意时刻,( t{Ray}) 对于经过每一座桥的愉悦度的绝对值小于等于(1000)

    输出格式:

    对于每一个询问(操作(S)(MAX)(MIN)),输出答案。


    树链剖分模板题,挂了好多个小时简直自闭了。

    奇怪的错误点:

    1. read()没读负数,最开始忘记生成负数据了一直拍不出来
    2. 若前向星的边的编号除2得到原始编号,应该从2开始编号,随机生成树的时候没打乱边的顺序没拍出来。

    Code:

    #include <cstdio>
    #include <cctype>
    const int N=2e5+10;
    int head[N],to[N<<1],edge[N<<1],Next[N<<1],cnt=1;
    void add(int u,int v,int w)
    {
        to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
        to[++cnt]=u,edge[cnt]=w,Next[cnt]=head[v],head[v]=cnt;
    }
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(!isdigit(c)) {if(c=='-') f=-f;c=getchar();}
        while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int num[N],dtp[N],ha[N],top[N],f[N],dfn[N],dep[N],siz[N],ws[N],dfs_clock=-1;
    void dfs1(int now)
    {
        siz[now]=1;
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(v!=f[now])
            {
                f[v]=now,dep[v]=dep[now]+1,num[i>>1]=v,dtp[v]=i;
                dfs1(v);
                siz[now]+=siz[v];
                if(siz[v]>siz[ws[now]]) ws[now]=v;
            }
        }
    }
    void dfs2(int now,int anc)
    {
        dfn[now]=++dfs_clock;
        ha[dfs_clock]=now;
        top[now]=anc;
        if(ws[now]) dfs2(ws[now],anc);
        for(int i=head[now];i;i=Next[i])
            if(!dfn[to[i]]&&to[i]!=1)
                dfs2(to[i],to[i]);
    }
    int sum[N<<2],mx[N<<2],mi[N<<2],tag[N<<2],tot,tmp;
    int n,m;char op[6];
    #define ls id<<1
    #define rs id<<1|1
    int max(int x,int y){return x>y?x:y;}
    int min(int x,int y){return x<y?x:y;}
    void swap(int &x,int &y){tmp=x,x=y,y=tmp;}
    void updata(int id)
    {
        mx[id]=max(mx[ls],mx[rs]);
        mi[id]=min(mi[ls],mi[rs]);
        sum[id]=sum[ls]+sum[rs];
    }
    void build(int id,int l,int r)
    {
        if(l==r)
        {
            sum[id]=mx[id]=mi[id]=edge[dtp[ha[l]]];
            return;
        }
        int mid=l+r>>1;
        build(ls,l,mid),build(rs,mid+1,r);
        updata(id);
    }
    void rev(int id)
    {
        mx[id]=-mx[id],mi[id]=-mi[id];
        swap(mx[id],mi[id]);
    }
    void pushdown(int id)
    {
        if(tag[id])
        {
            sum[ls]=-sum[ls],sum[rs]=-sum[rs];
            rev(ls),rev(rs);
            tag[ls]^=1,tag[rs]^=1;
            tag[id]^=1;
        }
    }
    void change(int id,int l,int r,int p,int d)
    {
        if(l==r)
        {
            mx[id]=mi[id]=sum[id]=d;
            return;
        }
        pushdown(id);
        int mid=l+r>>1;
        if(p<=mid) change(ls,l,mid,p,d);
        else change(rs,mid+1,r,p,d);
        updata(id);
    }
    void Reverse(int id,int L,int R,int l,int r)
    {
        if(L==l&&R==r)
        {
            tag[id]^=1,sum[id]=-sum[id],rev(id);
            return;
        }
        pushdown(id);
        int Mid=L+R>>1;
        if(r<=Mid) Reverse(ls,L,Mid,l,r);
        else if(l>Mid) Reverse(rs,Mid+1,R,l,r);
        else Reverse(ls,L,Mid,l,Mid),Reverse(rs,Mid+1,R,Mid+1,r);
        updata(id);
    }
    void modify(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]>=dep[top[y]])
            {
                Reverse(1,1,n,dfn[top[x]],dfn[x]);
                x=f[top[x]];
            }
            else
            {
                Reverse(1,1,n,dfn[top[y]],dfn[y]);
                y=f[top[y]];
            }
        }
        if(dep[x]<dep[y]) swap(x,y);
        if(x!=y) Reverse(1,1,n,dfn[y]+1,dfn[x]);
    }
    int querys(int id,int L,int R,int l,int r)
    {
        if(l==L&&r==R) return sum[id];
        pushdown(id);
        int Mid=L+R>>1;
        if(r<=Mid) return querys(ls,L,Mid,l,r);
        else if(l>Mid) return querys(rs,Mid+1,R,l,r);
        else return querys(ls,L,Mid,l,Mid)+querys(rs,Mid+1,R,Mid+1,r);
    }
    int querysum(int x,int y)
    {
        int s=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]>=dep[top[y]])
            {
                s+=querys(1,1,n,dfn[top[x]],dfn[x]);
                x=f[top[x]];
            }
            else
            {
                s+=querys(1,1,n,dfn[top[y]],dfn[y]);
                y=f[top[y]];
            }
        }
        if(dep[x]<dep[y]) swap(x,y);
        if(x!=y) s+=querys(1,1,n,dfn[y]+1,dfn[x]);
        return s;
    }
    int querymi(int id,int L,int R,int l,int r)
    {
        if(l==L&&r==R) return mi[id];
        pushdown(id);
        int Mid=L+R>>1;
        if(r<=Mid) return querymi(ls,L,Mid,l,r);
        else if(l>Mid) return querymi(rs,Mid+1,R,l,r);
        else return min(querymi(ls,L,Mid,l,Mid),querymi(rs,Mid+1,R,Mid+1,r));
    }
    int querymin(int x,int y)
    {
        int s=N;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]>=dep[top[y]])
            {
                s=min(s,querymi(1,1,n,dfn[top[x]],dfn[x]));
                x=f[top[x]];
            }
            else
            {
                s=min(s,querymi(1,1,n,dfn[top[y]],dfn[y]));
                y=f[top[y]];
            }
        }
        if(dep[x]<dep[y]) swap(x,y);
        if(x!=y) s=min(s,querymi(1,1,n,dfn[y]+1,dfn[x]));
        return s;
    }
    int querymx(int id,int L,int R,int l,int r)
    {
        if(l==L&&r==R) return mx[id];
        pushdown(id);
        int Mid=L+R>>1;
        if(r<=Mid) return querymx(ls,L,Mid,l,r);
        else if(l>Mid) return querymx(rs,Mid+1,R,l,r);
        else return max(querymx(ls,L,Mid,l,Mid),querymx(rs,Mid+1,R,Mid+1,r));
    }
    int querymax(int x,int y)
    {
        int s=-N;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]>=dep[top[y]])
            {
                s=max(s,querymx(1,1,n,dfn[top[x]],dfn[x]));
                x=f[top[x]];
            }
            else
            {
                s=max(s,querymx(1,1,n,dfn[top[y]],dfn[y]));
                y=f[top[y]];
            }
        }
        if(dep[x]<dep[y]) swap(x,y);
        if(x!=y) s=max(s,querymx(1,1,n,dfn[y]+1,dfn[x]));
        return s;
    }
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        n=read();
        int u,v,w;rep(i,1,(n-1)) u=read()+1,v=read()+1,w=read(),add(u,v,w);
        dep[1]=1,dfs1(1),dfs2(1,1);
        m=read();
        build(1,1,--n);
        rep(i,1,m)
        {
            scanf("%s",op);
            u=read()+1,v=read()+1;
            if(op[0]=='C') change(1,1,n,dfn[num[u-1]],v-1);
            else if(op[0]=='N') modify(u,v);
            else if(op[0]=='S') printf("%d
    ",querysum(u,v));
            else if(op[1]=='A') printf("%d
    ",querymax(u,v));
            else printf("%d
    ",querymin(u,v));
        }
        return 0;
    }
    

    2018.11.5

  • 相关阅读:
    观察者模式的结构
    策略模式
    EJB 配置多个数据源
    EJB3 调用的存储过程
    Android学习笔记_49_Android中自定义属性(attrs.xml,TypedArray的使用)
    Android学习笔记_48_若水新闻客户端源码剖析
    博客样式
    oracle 基础知识(四)常用函数
    oracle 基础知识(三)
    oracle 基础语法(二)
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9910931.html
Copyright © 2020-2023  润新知