poj 3237 tree 树链剖分模板

本文介绍了一种高效的数据结构处理方法——树链剖分结合线段树的应用,用于解决区间更新及查询等问题。通过具体实现代码展示了如何进行树的构建、树链剖分、线段树构建与维护等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码能力不行玩这个有点坑啊。。。
区间更新 最大值最小值反转就行了

//树链剖分
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define LL long long
#define maxn 100005
#define lson i<<1
#define rson (i<<1)+1
using namespace std;
int son[maxn],deep[maxn],siz[maxn],fa[maxn],top[maxn],l,n;//树
struct edge{
    int a,b,c;
}e[maxn];

int last[maxn*2],link[maxn*2],fron[maxn*2],edgel;//链式前向星

int maxi[maxn*4],mini[maxn*4],flag[maxn*4],ha[maxn],va[maxn];//线段树

char s[5];

void add(int a,int b)
{
     link[edgel] = b;
     fron[edgel] = last[a];
     last[a] = edgel;
     edgel++;
}
void dfs(int pre)
{
     siz[pre] = 1,son[pre] = 0;
     for(int i=last[pre];i!=-1;i = fron[i])
        if(link[i]!=fa[pre])
        {
           fa[link[i]] = pre;
           deep[link[i]] = deep[pre]+1;
           dfs(link[i]);
           if(siz[link[i]]>siz[son[pre]])son[pre] = link[i];
           siz[pre]+=siz[link[i]];
        }
}
void dfs2(int pre,int root)
{
     top[pre] = root;
     ha[pre] = ++l;
     if(son[pre])dfs2(son[pre],root);
     for(int i=last[pre];i!=-1;i = fron[i])
         if(link[i]!=son[pre]&&link[i]!=fa[pre])dfs2(link[i],link[i]);
}

void build(int i,int l,int r)
{
      flag[i] = 1;
      if(l==r)
      {
          maxi[i] = va[l];
          mini[i] = va[l];
          return ;
      }
      int mid = (l+r)/2;
      build(lson,l,mid);
      build(rson,mid+1,r);
      maxi[i] = max(maxi[lson],maxi[rson]);
      mini[i] = min(mini[lson],mini[rson]);
}
void pushUp(int i)
{
       maxi[i] = max(maxi[lson],maxi[rson]);
       mini[i] = min(mini[lson],mini[rson]);
}
void pushDown(int i,int l,int r)
{
     int a = maxi[i],b = mini[i];
     if(l!=r&&flag[i]==-1)
     {
         flag[lson] *= flag[i];
         flag[rson] *= flag[i];
         int a = maxi[lson],b = mini[lson];
         maxi[lson] = -1*b;
         mini[lson] = -1*a;
         a = maxi[rson],b = mini[rson];
         maxi[rson] = -1*b;
         mini[rson] = -1*a;
     }
     flag[i] =  1;
}
void update(int i,int l,int r,int L,int R)
{
      if(l==L&&r==R)
      {
          flag[i]*=-1;
          int a = maxi[i],b = mini[i];
          maxi[i] = -b;
          mini[i] = -a;
          return ;
      }
      pushDown(i,l,r);
      int mid = (l+r)/2;
      if(R<=mid)update(lson,l,mid,L,R);
      else if(L>mid)update(rson,mid+1,r,L,R);
      else {
        update(lson,l,mid,L,mid);
        update(rson,mid+1,r,mid+1,R);
      }
      pushUp(i);
}
void updateChange(int i,int l,int r,int L,int R,int c)
{
      if(l==L&&r==R)
      {
          maxi[i] = c;
          mini[i] = c;
          return ;
      }
      pushDown(i,l,r);
      int mid = (l+r)/2;
      if(R<=mid)updateChange(lson,l,mid,L,R,c);
      else if(L>mid)updateChange(rson,mid+1,r,L,R,c);
      pushUp(i);
}
int query(int i,int l,int r,int L,int R)
{
    if(l==L&&r==R)
    {
        return maxi[i];
    }
    pushDown(i,l,r);
    int mid = (l+r)/2;
    if(R<=mid)return query(lson,l,mid,L,R);
    else if(L>mid)return query(rson,mid+1,r,L,R);
    return max(query(lson,l,mid,L,mid),query(rson,mid+1,r,mid+1,R));
}
int find(int a,int b)
{
    int faa = top[a],fab = top[b],ans = -10000000;
    while(faa!=fab)
    {
         if(deep[faa]<deep[fab])
         {
             swap(faa,fab);
             swap(a,b);
         }
         ans = max(ans, query(1,1,l,ha[faa],ha[a]));
         a = fa[faa];
         faa = top[a];
    }
    if(a==b)return ans;
    if(deep[a]<deep[b])swap(a,b);
    ans = max(ans, query(1,1,l,ha[son[b]],ha[a]));
    return ans;
}
void change(int a,int b)
{
    int faa = top[a],fab = top[b];
    while(faa!=fab)
    {
         if(deep[faa]<deep[fab])
         {
             swap(faa,fab);
             swap(a,b);
         }
         update(1,1,l,ha[faa],ha[a]);
         a = fa[faa];
         faa = top[a];
    }
    if(a==b)return ;
    if(deep[a]<deep[b])swap(a,b);
    update(1,1,l,ha[son[b]],ha[a]);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
       int n,a,b,c;
       scanf("%d",&n);
       memset(last,-1,sizeof(last));
       fa[1] = 0,deep[1] = 1;l = 0,edgel = 0,va[1] = 0;
       for(int i=1;i<n;i++)
       {
           scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
           add(e[i].a,e[i].b);
           add(e[i].b,e[i].a);
       }
       dfs(1);
       dfs2(1,1);
       for(int i=1;i<n;i++)
       {
           if(deep[e[i].a]<deep[e[i].b])swap(e[i].a,e[i].b);
           va[ha[e[i].a]] = e[i].c;
       }
       build(1,1,l);
       while(scanf("%s",s))
       {
           int a,b;
           if(s[0]=='Q')
           {
               scanf("%d%d",&a,&b);
               printf("%d\n",find(a,b));
           }
           else if(s[0]=='C')
           {
               scanf("%d%d",&a,&b);
               updateChange(1,1,l,ha[e[a].a],ha[e[a].a],b);
           }
           else if(s[0]=='N')
           {
               scanf("%d%d",&a,&b);
               change(a,b);
           }
           else break;
       }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值