poj 3237


维护边上信息的树链剖分,
我是将父边的信息储存在结点上,
然后按与维护点值类似方法处理的。


注意本题有多组数据,对于每组数据,
树上信息和线段树一定要重新赋值!!!

本蒟蒻因此WA了好多次。。。。。。


#include<map>
#include<queue>
#include<stack>
#include<utility>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<algorithm>
#define Mp(x,y) std::make_pair(x,y)

const int MAXN = 1e5+5, INF = 1e9;

struct Edge{int v,w,next; Edge(int v = 0,int w = 0,int next = 0):v(v),w(w),next(next){}};

int n , m;

int head[MAXN] = {0}, el = 0;
Edge edge[MAXN<<1] = {0};

int fa[MAXN] = {0},size[MAXN] = {0},dep[MAXN] = {0};
int top[MAXN] = {0},son[MAXN] = {0};
int fc[MAXN] = {0} ,dl = 0, nfc[MAXN] = {0};
int efc[MAXN] = {0}, fe[MAXN] = {0};

namespace seg
{
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)

    struct TreeNode{int max,min,tag;};
    int value;
    TreeNode tree[MAXN<<2] = {0};

    void PushDown(int x)
    {
        if(tree[x].tag)
        {
            std::swap(tree[L(x)].max,tree[L(x)].min);
            tree[L(x)].max*=-1,tree[L(x)].min*=-1;
            std::swap(tree[R(x)].max,tree[R(x)].min);
            tree[R(x)].max*=-1,tree[R(x)].min*=-1;

            tree[L(x)].tag ^= 1, tree[R(x)].tag ^= 1;
            tree[x].tag = 0;
        }
    }
    void Update(int x)
    {
        tree[x].max = std::max(tree[L(x)].max,tree[R(x)].max);
        tree[x].min = std::min(tree[L(x)].min,tree[R(x)].min);
    }
    void Build(int ll,int rr,int si)
    {
       tree[si].tag = 0;

       if(ll == rr)
            tree[si].max = tree[si].min = edge[fe[nfc[ll]]].w;
       else
       {
            int mid = (ll + rr) >>1;
            if(ll <= mid)Build(ll,mid,L(si));
            if(mid < rr)Build(mid+1,rr,R(si));
            Update(si);
        }
    }
    void Change(int ll,int rr,int l,int r,int si)
    {
        if(ll == l && rr == r)
            tree[si].max = tree[si].min = value;
        else
        {
            PushDown(si);
            int mid = (ll+rr)>>1;
            if(r <= mid)
                Change(ll,mid,l,r,L(si));
            else if(mid < l)
                Change(mid+1,rr,l,r,R(si));
            else
            {
                Change(ll,mid,l,mid,L(si));
                Change(mid+1,rr,mid+1,r,R(si));
            }
            Update(si);
        }
    }
    void Color(int ll,int rr,int l,int r,int si)
    {
        if(ll == l && rr == r)
        {
            tree[si].tag ^= 1;
            std::swap(tree[si].max,tree[si].min);
            tree[si].max*=-1,tree[si].min*=-1;
        }
        else
        {
            PushDown(si);
            int mid = (ll+rr)>>1;
            if(r <= mid)
                Color(ll,mid,l,r,L(si));
            else if(mid < l)
                Color(mid+1,rr,l,r,R(si));
            else
            {
                Color(ll,mid,l,mid,L(si));
                Color(mid+1,rr,mid+1,r,R(si));
            }
            Update(si);
        }
    }
    int Query(int ll,int rr,int l,int r,int si)
    {
        if(ll == l && rr == r)
            return tree[si].max;
        else
        {
            PushDown(si);
            int mid = (ll+rr)>>1;
            if(r <= mid)
                return Query(ll,mid,l,r,L(si));
            else if(mid < l)
                return Query(mid+1,rr,l,r,R(si));
            else
            {
                int ret1, ret2;
                ret1 = Query(ll,mid,l,mid,L(si));
                ret2 = Query(mid+1,rr,mid+1,r,R(si));
                return std::max(ret1,ret2);
            }
            Update(si);
         }
    }

#undef L
#undef R
}


void NewEdge(int u,int v,int w)
{++el; edge[el] = Edge(v,w,head[u]); head[u] = el;}
void Clear()
{el = dl = 0; for(int i = 1; i <= n; i++) fa[i] = head[i] = 0;}
void Change(int p,int x)
{
    seg::value = x; seg::Change(1,n,p,p,1);
}
void Negate(int x,int y)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] > dep[top[y]])
             std::swap(x,y);

        seg::Color(1,n,fc[top[y]],fc[y],1);

        y = fa[top[y]];
    }

    if(x != y)
    {
      if(dep[x] > dep[y]) std::swap(x,y);
       seg::Color(1,n,fc[son[x]],fc[y],1);
    }
}
int Query(int x,int y)
{
    int ret = -INF;

    while(top[x] != top[y])
    {
        if(dep[top[x]] > dep[top[y]])
             std::swap(x,y);

        int tmp = seg::Query(1,n,fc[top[y]],fc[y],1);
        ret = std::max(ret,tmp);

        y = fa[top[y]];
    }
    if(x != y)
    {
      if(dep[x] > dep[y]) std::swap(x,y);

      int tmp = seg::Query(1,n,fc[son[x]],fc[y],1);
      ret = std::max(ret,tmp);
    }
    return ret;
}
void DFS(int a)
{
    dep[a] = dep[fa[a]] + 1;

    size[a] = 1, son[a] = 0;
    for(int i = head[a]; i ; i = edge[i].next)
    {
        int p = edge[i].v;
        if(p == fa[a])continue;

        efc[(i+(i&1))>>1] = p;
        fa[p] = a, fe[p] = i;

        DFS(p);

        size[a] += p;

        if(size[p] > size[son[a]])
          son[a] = p;
    }
}
void Build(int a)
{
    nfc[++dl] = a, fc[a] = dl;

    top[a] = a;
    if(son[fa[a]] == a)
        top[a] = top[fa[a]];

    if(son[a]) Build(son[a]);

    for(int i = head[a]; i ; i = edge[i].next)
    {
        int p = edge[i].v;
        if(p == fa[a] || p == son[a])continue;

        Build(p);
    }
}

int main()
{
    int T;

#ifndef ONLINE_JUDGE
    freopen("poj3237.in","r",stdin);
    freopen("poj3237.out","w",stdout);
#endif

    std::cin >> T;

    while(T--)
    {
        std::cin >> n;  Clear();
        for(int i = 1,a,b,w; i < n; i++)
        {
           scanf("%d%d%d",&a,&b,&w);
            NewEdge(a,b,w);NewEdge(b,a,w);
        }
        DFS(1); Build(1); seg::Build(1,n,1);

        bool flag = true;
        while(flag)
        {
            char str[10];int a , b;
            scanf("%s",str);

            switch(str[0])
            {
                case 'D':
                    flag = false;
                    break;
                case 'C':
                    scanf("%d%d",&a,&b);
                    Change(fc[efc[a]],b);
                    break;
                case 'N':
                    scanf("%d%d",&a,&b);
                    Negate(a,b);
                    break;
                case 'Q':
                    scanf("%d%d",&a,&b);
                    printf("%d\n",Query(a,b));
                    break;
            }
        }
    }


#ifndef ONLINE_JUDGE
    fprintf(stderr,"%f",clock()*1.0/CLOCKS_PER_SEC);

    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值