zoukankan      html  css  js  c++  java
  • POJ 3237 /// 树链剖分 线段树区间修改(*-1)

    题目大意:

    给定树的N个结点 编号为1到N 给定N-1条边的边权。

    三种操作: 

    CHANGE k w:将第 k 条边的权值改成 w。 

    NEGATE x y:将x到y的路径上所有边的权值乘 -1。 

    QUERY x y:找出x到y的路径上所有边的最大权值。


    单点更新 区间更新  区间查询

    由于第二个操作是乘 -1 所以需要同时维护最大值和最小值

    所以 lazy用来标记是否乘-1 0表示不乘-1 1表示乘-1

    http://www.cnblogs.com/HDUjackyan/p/9279777.html

    #include <stdio.h>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define mem(i,j) memset(i,j,sizeof(i))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define root 1,n,1
    
    const int maxn=1e4+5;
    int n;
    
    struct IntervalTree {
        struct EDGE { int to,ne; }e[maxn<<1];
        int head[maxn], tot;
        void addE(int u,int v) {
            e[tot].to=v;
            e[tot].ne=head[u];
            head[u]=tot++;
        }
    
        int fa[maxn], son[maxn], dep[maxn], num[maxn];
        int top[maxn], p[maxn], fp[maxn], pos;
    
        void init() {
            tot=1; mem(head,0);
            pos=0; mem(son,0);
        }
    
        struct TREE {
            int Max,Min,lazy;
        }tree[maxn<<2];
    
    // --------------------以下是线段树-------------------------
    
        void pushUp(int rt) {
            tree[rt].Max=max(tree[rt<<1].Max,tree[rt<<1|1].Max);
            tree[rt].Min=min(tree[rt<<1].Min,tree[rt<<1|1].Min);
        }
        void pushDown(int rt,int m) {
            if(m==0) return;
            if(tree[rt].lazy) {
                tree[rt<<1].Max*=-1;
                tree[rt<<1].Min*=-1;
                tree[rt<<1].lazy^=1;
                tree[rt<<1|1].Max*=-1;
                tree[rt<<1|1].Min*=-1;
                tree[rt<<1|1].lazy^=1;
                swap(tree[rt<<1].Max,tree[rt<<1].Min);
                swap(tree[rt<<1|1].Max,tree[rt<<1|1].Min);
                tree[rt].lazy=0;
            }
        }
        void build(int l,int r,int rt) {
            if(l==r) {
                tree[rt].Max=tree[rt].Min=tree[rt].lazy=0;
                return;
            }
            int m=(l+r)>>1;
            build(lson), build(rson);
            pushUp(rt);
        }
        void update1(int k,int w,int l,int r,int rt) {
            if(l==r) {
                tree[rt].Max=tree[rt].Min=w;
                tree[rt].lazy=0;
                return;
            }
            pushDown(rt,r-l+1);
            int m=(l+r)>>1;
            if(k<=m) update1(k,w,lson);
            else update1(k,w,rson);
            pushUp(rt);
        }
        void update2(int L,int R,int l,int r,int rt) {
            if(L<=l && r<=R) {
                tree[rt].Max*=-1;
                tree[rt].Min*=-1;
                tree[rt].lazy^=1;
                swap(tree[rt].Max,tree[rt].Min);
                return ;
            }
            pushDown(rt,r-l+1);
            int m=(l+r)>>1;
            if(L<=m) update2(L,R,lson);
            if(R>m) update2(L,R,rson);
            pushUp(rt);
        }
        int query(int L,int R,int l,int r,int rt) {
            if(L<=l && r<=R) return tree[rt].Max;
            pushDown(rt,r-l+1);
            int m=(l+r)>>1, res=-INF;
            if(L<=m) res=max(res,query(L,R,lson));
            if(R>m) res=max(res,query(L,R,rson));
            pushUp(rt);
            return res;
        }
    
    // --------------------以上是线段树-------------------------
    
    // --------------------以下是树链剖分-------------------------
    
        void dfs1(int u,int pre,int d) {
            dep[u]=d; fa[u]=pre; num[u]=1;
            for(int i=head[u];i;i=e[i].ne) {
                int v=e[i].to;
                if(v!=fa[u]) {
                    dfs1(v,u,d+1);
                    num[u]+=num[v];
                    if(!son[u] || num[v]>num[son[u]])
                        son[u]=v;
                }
            }
        }
        void dfs2(int u,int sp) {
            top[u]=sp; p[u]=++pos; fp[p[u]]=u;
            if(!son[u]) return;
            dfs2(son[u],sp);
            for(int i=head[u];i;i=e[i].ne) {
                int v=e[i].to;
                if(v!=son[u] && v!=fa[u])
                    dfs2(v,v);
            }
        }
        int queryPath(int x,int y) {
            int fx=top[x], fy=top[y], ans=-INF;
            while(fx!=fy) {
                if(dep[fx]>dep[fy]) {
                    ans=max(ans,query(p[fx],p[x],root));
                    x=fa[fx];
                } else {
                    ans=max(ans,query(p[fy],p[y],root));
                    y=fa[fy];
                }
                fx=top[x], fy=top[y];
            }
            if(x==y) return ans;
            if(dep[x]>dep[y]) swap(x,y);
            return max(ans,query(p[son[x]],p[y],root));
        }
        void updatePath(int x,int y) {
            int fx=top[x], fy=top[y];
            while(fx!=fy) {
                if(dep[fx]>dep[fy]) {
                    update2(p[fx],p[x],root);
                    x=fa[fx];
                } else {
                    update2(p[fy],p[y],root);
                    y=fa[fy];
                }
                fx=top[x], fy=top[y];
            }
            if(x==y) return ;
            if(dep[x]>dep[y]) swap(x,y);
            update2(p[son[x]],p[y],root);
        }
    
    // --------------------以上是树链剖分-------------------------
    
        void initQTree() {
            dfs1(1,0,0), dfs2(1,1);
            build(root);
        }
    }T;
    int E[maxn][3];
    
    int main()
    {
        int t; scanf("%d",&t);
        while(t--) {
            scanf("%d",&n);
            T.init();
            for(int i=1;i<n;i++) {
                int u,v,w; scanf("%d%d%d",&u,&v,&w);
                E[i][0]=u, E[i][1]=v, E[i][2]=w;
                T.addE(u,v), T.addE(v,u);
            }
            T.initQTree();
            for(int i=1;i<n;i++) {
                if(T.dep[E[i][0]]>T.dep[E[i][1]])
                    swap(E[i][0],E[i][1]); //puts("OK");
                T.update1(T.p[E[i][1]],E[i][2],root);
            }
            while(1) {
                char s[10]; scanf("%s",s);
                if(s[0]=='D') break;
                int x,y; scanf("%d%d",&x,&y);
                if(s[0]=='Q')
                    printf("%d
    ",T.queryPath(x,y));
                else if(s[0]=='C')
                    T.update1(T.p[E[x][1]],y,root);
                else if(s[0]=='N')
                    T.updatePath(x,y);
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Java进阶10 内存管理与垃圾回收
    C编译: makefile基础
    Java基础09 类数据与类方法
    Java进阶06 容器
    C编译: 动态连接库 (.so文件)
    Java基础10 接口的继承与抽象类
    纸上谈兵: 左倾堆 (leftist heap)
    Java进阶02 异常处理
    Java进阶05 多线程
    Java基础12 类型转换与多态
  • 原文地址:https://www.cnblogs.com/zquzjx/p/9998751.html
Copyright © 2011-2022 走看看