zoukankan      html  css  js  c++  java
  • BZOJ2157: 旅游

    【传送门:BZOJ3676


    简要题意:

      给出一棵树,树上的边有权值(可正可负),对这棵树有5种操作:

      1.SUM x y求出x点到y点所经过的边权和

      2.MAX x y求出x点到y点所经过的边的最大边权

      3.MIN x y求出x点到y点所经过的边的最小边权

      4.C x y将输入的第x条边的边权改为y

      5.N x y将x点到y点所经过的边的边权全部变成自己的相反数


    题解:

      很显然,在树上求路径特征值,用树链剖分

      对于边权,就把边权变为这条边深度最深的点的点权,然后在求特征值的时候注意一下就行了

      关键是相反数问题,注意:假设一段区间的和为s,最大值为mx,最小值为mn,那么取相反数后,这段区间的和为-s,最大值为-mn,最小值为-mx

      然后因为修改的是区间,所以要用lazy标记来继承状态

      因为原题的点编号为0到n-1,有点恶心,所以把编号改为1到n

      然而我,就因为在一个操作中没有x++,y++,卡了一个中午


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    struct node
    {
        int x,y,next;
    }a[41000];int len,last[21000];
    struct trnode
    {
        int l,r,lc,rc,mn,mx,s;
        int lazy;
        trnode()
        {
            lazy=0;
        }
    }tr[41000];int trlen;
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    void update(int x)
    {
        int lc=tr[x].lc,rc=tr[x].rc;
        int mn,mx;
        if(lc!=-1)
        {
            mn=tr[lc].mn;mx=tr[lc].mx;
            tr[lc].mn=-mx;tr[lc].mx=-mn;
            tr[lc].s=-tr[lc].s;
            tr[lc].lazy^=1;
        }
        if(rc!=-1)
        {
            mn=tr[rc].mn;mx=tr[rc].mx;
            tr[rc].mn=-mx;tr[rc].mx=-mn;
            tr[rc].s=-tr[rc].s;
            tr[rc].lazy^=1;
        }
        tr[x].lazy=0;
    }
    void follow(int x)
    {
        int lc=tr[x].lc,rc=tr[x].rc;
        tr[x].s=tr[lc].s+tr[rc].s;
        tr[x].mx=max(tr[lc].mx,tr[rc].mx);
        tr[x].mn=min(tr[lc].mn,tr[rc].mn);
    }
    void bt(int l,int r)
    {
        trlen++;int now=trlen;
        tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;
        tr[now].mn=tr[now].mx=0;tr[now].s=0;
        if(l<r)
        {
            int mid=(l+r)/2;
            tr[now].lc=trlen+1;bt(l,mid);
            tr[now].rc=trlen+1;bt(mid+1,r);
        }
    }
    int tot[21000],fa[21000],dep[21000],son[21000];
    void pre_tree_node(int x)
    {
        tot[x]=1;son[x]=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa[x])
            {
                dep[y]=dep[x]+1;
                fa[y]=x;
                pre_tree_node(y);
                tot[x]+=tot[y];
                if(tot[y]>tot[son[x]]) son[x]=y;
            }
        }
    }
    int ys[21000],z,top[21000];
    void pre_tree_edge(int x,int tp)
    {
        ys[x]=++z;top[x]=tp;
        if(son[x]!=0) pre_tree_edge(son[x],tp);
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa[x]&&y!=son[x]) pre_tree_edge(y,y);
        }
    }
    void add(int now,int x,int c)
    {
        if(tr[now].l==tr[now].r)
        {
            tr[now].s=c;
            tr[now].mx=tr[now].mn=tr[now].s;
            return ;
        }
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy==1) update(now);
        if(x<=mid) add(lc,x,c);
        else add(rc,x,c);
        follow(now);
    }
    void xf(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r)
        {
            tr[now].lazy^=1;
            int mn=tr[now].mn,mx=tr[now].mx;
            tr[now].mx=-mn;tr[now].mn=-mx;
            tr[now].s=-tr[now].s;
            return ;
        }
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy==1) update(now);
        if(r<=mid) xf(lc,l,r);
        else if(l>mid) xf(rc,l,r);
        else
        {
            xf(lc,l,mid);xf(rc,mid+1,r);
        }
        follow(now);
    }
    void change(int x,int y)
    {
        int tx=top[x],ty=top[y];
        while(tx!=ty)
        {
            if(dep[tx]>dep[ty])
            {
                swap(tx,ty);
                swap(x,y);
            }
            xf(1,ys[ty],ys[y]);
            y=fa[ty];ty=top[y];
        }
        if(x!=y)
        {
            if(dep[x]>dep[y]) swap(x,y);
            xf(1,ys[son[x]],ys[y]);
        }
    }
    int getsum(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r) return tr[now].s;
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy==1) update(now);
        if(r<=mid) return getsum(lc,l,r);
        else if(l>mid) return getsum(rc,l,r);
        else return getsum(lc,l,mid)+getsum(rc,mid+1,r);
    }
    int findmax(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r) return tr[now].mx;
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy==1) update(now);
        if(r<=mid) return findmax(lc,l,r);
        else if(l>mid) return findmax(rc,l,r);
        else return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
    }
    int findmin(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r) return tr[now].mn;
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy==1) update(now);
        if(r<=mid) return findmin(lc,l,r);
        else if(l>mid) return findmin(rc,l,r);
        else return min(findmin(lc,l,mid),findmin(rc,mid+1,r));
    }
    int solve(int x,int y,int t)
    {
        if(t==1)
        {
            int ans=0,tx=top[x],ty=top[y];
            while(tx!=ty)
            {
                if(dep[tx]>dep[ty])
                {
                    swap(tx,ty);
                    swap(x,y);
                }
                ans+=getsum(1,ys[ty],ys[y]);
                y=fa[ty];ty=top[y];
            }
            if(x==y) return ans;
            else
            {
                if(dep[x]>dep[y]) swap(x,y);
                return ans+getsum(1,ys[son[x]],ys[y]);
            }
        }
        else if(t==2)
        {
            int ans=-999999999,tx=top[x],ty=top[y];
            while(tx!=ty)
            {
                if(dep[tx]>dep[ty])
                {
                    swap(tx,ty);
                    swap(x,y);
                }
                ans=max(ans,findmax(1,ys[ty],ys[y]));
                y=fa[ty];ty=top[y];
            }
            if(x==y) return ans;
            else
            {
                if(dep[x]>dep[y]) swap(x,y);
                return max(ans,findmax(1,ys[son[x]],ys[y]));
            }
        }
        else if(t==3)
        {
            int ans=999999999,tx=top[x],ty=top[y];
            while(tx!=ty)
            {
                if(dep[tx]>dep[ty])
                {
                    swap(tx,ty);
                    swap(x,y);
                }
                ans=min(ans,findmin(1,ys[ty],ys[y]));
                y=fa[ty];ty=top[y];
            }
            if(x==y) return ans;
            else
            {
                if(dep[x]>dep[y]) swap(x,y);
                return min(ans,findmin(1,ys[son[x]],ys[y]));
            }
        }
    }
    struct enode
    {
        int x,y,d;
    }e[21000];
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int n;
        scanf("%d",&n);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);
            e[i].x++;e[i].y++;
            ins(e[i].x,e[i].y);ins(e[i].y,e[i].x);
        }
        dep[1]=0;fa[1]=0;pre_tree_node(1);
        z=0;pre_tree_edge(1,1);
        trlen=0;bt(1,z);
        for(int i=1;i<n;i++) if(dep[e[i].x]>dep[e[i].y]) swap(e[i].x,e[i].y);
        for(int i=1;i<n;i++) add(1,ys[e[i].y],e[i].d);
        int m;
        scanf("%d",&m);
        char st[5];
        for(int i=1;i<=m;i++)
        {
            scanf("%s",st+1);
            int x,y;
            scanf("%d%d",&x,&y);
            if(st[1]=='C')
            {
                add(1,ys[e[x].y],y);
                continue;
            }
            x++;y++;
            if(st[1]=='N') change(x,y);
            if(st[1]=='S') printf("%d
    ",solve(x,y,1));
            if(st[1]=='M'&&st[2]=='A') printf("%d
    ",solve(x,y,2));
            if(st[1]=='M'&&st[2]=='I') printf("%d
    ",solve(x,y,3));
        }
        return 0;
    }

     

  • 相关阅读:
    C. Tesla (模拟 + 思维)
    E
    E. Ehab's REAL Number Theory Problem (bfs + 思维)
    uva 12307
    P4249 [WC2007]剪刀石头布
    luoguP4003 无限之环
    luoguP4068 [SDOI2016]数字配对
    有源汇有上下界最小流
    有源汇有上下界最大流
    无源汇有上下界可行流
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8483313.html
Copyright © 2011-2022 走看看