POJ-3237-Tree

378 篇文章 0 订阅

学了树链剖分做的第二道练习题,这个题比较麻烦的是取反那,也就是每次乘以-1,同样的转成线段树进行维护,我在有个地方应该更新son[u],的时候直接+1了,导致WA了超多。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e5+100;
const int maxm=maxn*2;
struct Edge
{
    int from;
    int to;
    int cost;
}E[maxn];
struct Node
{
    int l;
    int r;
    int maxi;
    int mini;
    int neg;
}t[maxn*4];
int e,head[maxn],pnt[maxm],nxt[maxm],cost[maxm];
int n,pre[maxn],size[maxn],son[maxn],dep[maxn],top[maxn],idx[maxn],pos[maxn],tree_clock;
void AddEdge(int u,int v,int c)
{
    pnt[e]=v;nxt[e]=head[u];cost[e]=c;head[u]=e++;
}
void Init()
{
    e=tree_clock=0;
    memset(head,-1,sizeof(head));
    memset(dep,0,sizeof(dep));
    pre[1]=0;
    size[0]=0;
}
void DFS(int u)
{
    size[u]=1;
    son[u]=0;
    for(int i=head[u];i!=-1;i=nxt[i])
        if(pnt[i]!=pre[u])
        {
            pre[pnt[i]]=u;
            dep[pnt[i]]=dep[u]+1;
            DFS(pnt[i]);
            size[u]+=size[pnt[i]];
            if(size[pnt[i]]>size[son[u]])
                son[u]=pnt[i];
        }
}
void dfs(int u,int top_node)
{
    top[u]=top_node;
    pos[u]=++tree_clock;
    idx[tree_clock]=u;
    if(son[u])
        dfs(son[u],top_node);
    for(int i=head[u];i!=-1;i=nxt[i])
        if(pnt[i]!=pre[u]&&pnt[i]!=son[u])
            dfs(pnt[i],pnt[i]);
}
void Build(int l,int r,int index)
{
    t[index].l=l;
    t[index].r=r;
    t[index].maxi=-inf;
    t[index].mini=inf;
    t[index].neg=0;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    Build(l,mid,index<<1);
    Build(mid+1,r,index<<1|1);
}
void UpdateNode(int index)
{
    swap(t[index].maxi,t[index].mini);
    t[index].maxi*=-1;
    t[index].mini*=-1;
}
void PushDown(int index)
{
    if(t[index].l==t[index].r)
        return;
    if(t[index].neg)
    {
        t[index<<1].neg^=1;
        t[index<<1|1].neg^=1;
        UpdateNode(index<<1);
        UpdateNode(index<<1|1);
        t[index].neg=0;
    }
}
void PushUp(int index)
{
    t[index].maxi=max(t[index<<1].maxi,t[index<<1|1].maxi);
    t[index].mini=min(t[index<<1].mini,t[index<<1|1].mini);
}
void UpdateT(int l,int r,int index,int  val)
{
    PushDown(index);
    if(t[index].l==l&&t[index].r==r)
    {
        if(val==inf)
        {
            t[index].neg=1;
            UpdateNode(index);
        }
        else
            t[index].mini=t[index].maxi=val;
        return;
    }
    int mid=(t[index].l+t[index].r)>>1;
    if(r<=mid)
        UpdateT(l,r,index<<1,val);
    else if(l>mid)
        UpdateT(l,r,index<<1|1,val);
    else
    {
        UpdateT(l,mid,index<<1,val);
        UpdateT(mid+1,r,index<<1|1,val);
    }
    PushUp(index);
}
int QueryT(int l,int r,int index)
{
    PushDown(index);
    if(t[index].l==l&&t[index].r==r)
        return t[index].maxi;
    int mid=(t[index].l+t[index].r)>>1;
    if(r<=mid)
        return QueryT(l,r,index<<1);
    else if(l>mid)
        return QueryT(l,r,index<<1|1);
    else
        return max(QueryT(l,mid,index<<1),QueryT(mid+1,r,index<<1|1));
}
void Update(int x,int y,int v)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        UpdateT(pos[top[x]],pos[x],1,v);
        x=pre[top[x]];
    }
    if(x==y)
        return;
    if(dep[x]>dep[y])
        swap(x,y);
    UpdateT(pos[son[x]],pos[y],1,v);
}
int Query(int x,int y)
{
    int ans=-inf;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        ans=max(ans,QueryT(pos[top[x]],pos[x],1));
        x=pre[top[x]];
    }
    if(x==y)
        return ans;
    if(dep[x]>dep[y])
        swap(x,y);
    ans=max(ans,QueryT(pos[son[x]],pos[y],1));
    return ans==-inf?0:ans;
}
void solve()
{
    DFS(1);
    dfs(1,1);
    Build(1,tree_clock,1);
    for(int i=1;i<n;i++)
    {
        int x=E[i].from;
        int y=E[i].to;
        if(dep[x]>dep[y])
            swap(E[i].from,E[i].to);
        UpdateT(pos[E[i].to],pos[E[i].to],1,E[i].cost);
    }
    while(1)
    {
        char op[20];
        scanf("%s",op);
        if(op[0]=='Q')
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",Query(l,r));
        }
        else if(op[0]=='C')
        {
            int ind,val;
            scanf("%d%d",&ind,&val);
            UpdateT(pos[E[ind].to],pos[E[ind].to],1,val);
        }
        else if(op[0]=='N')
        {
            int l,r;
            scanf("%d%d",&l,&r);
            Update(l,r,inf);
        }
        else
            break;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&E[i].from,&E[i].to,&E[i].cost);
            AddEdge(E[i].from,E[i].to,E[i].cost);
            AddEdge(E[i].to,E[i].from,E[i].cost);
        }
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值