POJ 3237 Tree(树链剖分 + 单点更新 + 区间更新 + 区间查询)

题目链接:POJ-3237 Tree


题意及思路:这道题就是在SPOJ-QTREE这道题目上加了区间更新关键就是权值取反部分怎么处理,取反后最大值将会是原来的最小值,所以既要存最大值,又要存最小值。取反后最大值为原来的最小值取反,最小值为原来的最大值取反。在这里我是用add这个数组当作懒标记数组,当一个区间取两次反时还是原来的最大值和最小值,因此要取add[rt]数组进行%2操作,当add[rt]为1的时候向下传递标记,否则不传递。


#include<stdio.h>
#include<algorithm>
#include<string.h>
#define N 100005
#define inf 0x3f3f3f3f
using namespace std;

struct node
{
    int v,next;
} edge[N<<2];

int e[N][3];
int son[N],dep[N],fa[N];
int id,tid[N],top[N],siz[N];
int cnt,pre[N];
int Max[N<<2],Min[N<<2],add[N<<2];
int T,n,a,b,c;
char op[5];

int Scan()
{
    int flag = 1,res = 0;
    char ch;
    while((ch = getchar()) == ' ' || ch == '\n');
    if(ch == '-') flag = -1;
    else res = ch - '0';
    while((ch = getchar()) != ' ' && ch != '\n')
        res = res * 10 +  ch - '0';
    return flag * res;
}

void init()
{
    cnt = id = 0;
    memset(pre, -1, sizeof(pre));
    memset(son, 0, sizeof(son));
    memset(siz, 0, sizeof(siz));
    memset(Max, -inf, sizeof(Max));
    memset(Min, inf, sizeof(Min));
    memset(add, 0, sizeof(add));
}

void addEdge(int u, int v)
{
    edge[cnt].v = v;
    edge[cnt].next = pre[u];
    pre[u] = cnt++;
}

void dfs1(int u, int f, int dp)
{
    fa[u] = f,dep[u] = dp,son[u] = 0,siz[u] = 1;
    for(int i = pre[u]; ~i; i=edge[i].next)
    {
        int v = edge[i].v;
        if(v != f)
        {
            dfs1(v, u, dp+1);
            siz[u] += siz[v];
            if(siz[v] > siz[son[u]])
                son[u] = v;
        }
    }
}

void dfs2(int u, int tp)
{
    top[u] = tp,tid[u] = ++id;
    if(son[u])
        dfs2(son[u], tp);
    for(int i = pre[u]; ~i; i=edge[i].next)
    {
        int v = edge[i].v;
        if(v != fa[u] && v != son[u])
            dfs2(v, v);
    }
}

void push_up(int rt)
{
    Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
    Min[rt] = min(Min[rt<<1], Min[rt<<1|1]);
}

void push_down(int rt)
{
    if(add[rt])
    {
        add[rt<<1] = (add[rt<<1] + 1) % 2;
        add[rt<<1|1] = (add[rt<<1|1] + 1) % 2;
        add[rt] = 0;
        int maxl = Max[rt<<1],maxr = Max[rt<<1|1];
        Max[rt<<1] = -Min[rt<<1];
        Min[rt<<1] = -maxl;
        Max[rt<<1|1] = -Min[rt<<1|1];
        Min[rt<<1|1] = -maxr;
        push_up(rt);
    }
}

void update_1(int rt, int l, int r, int pos, int v)
{
    if(l == r && l == pos)
    {
        add[rt] = 0;
        Max[rt] = Min[rt] = v;
        return ;
    }
    push_down(rt);
    int mid = (l + r) >> 1;
    if(pos <= mid)
        update_1(rt<<1, l, mid, pos, v);
    else update_1(rt<<1|1, mid+1, r, pos, v);
    push_up(rt);
}

void deal()
{
    dfs1(1, 1, 1);
    dfs2(1, 1);
    for(int i = 1; i < n; ++i)
    {
        if(dep[e[i][0]] > dep[e[i][1]])
            swap(e[i][0], e[i][1]);
        update_1(1, 2, n, tid[e[i][1]], e[i][2]);
    }
}

void update_2(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && r <= qr)
    {
        add[rt] = (add[rt] + 1) % 2;
        int mmax = Max[rt];
        Max[rt] = -Min[rt],Min[rt] = -mmax;
        return ;
    }
    int mid = (l + r) >> 1;
    push_down(rt);
    if(ql <= mid)
        update_2(rt<<1, l, mid, ql, qr);
    if(qr > mid)
        update_2(rt<<1|1, mid+1, r, ql, qr);
    push_up(rt);
}

void lca_up(int u, int v)
{
    while(top[u] != top[v])
    {
        if(dep[top[u]] < dep[top[v]])
            swap(u, v);
        update_2(1, 2, n, tid[top[u]], tid[u]);
        u = fa[top[u]];
    }
    if(u != v)
    {
        if(dep[u] > dep[v])
            swap(u, v);
        update_2(1, 2, n, tid[u]+1, tid[v]);
    }
}

int query(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && r <= qr)
        return Max[rt];
    int mid = (l + r) >> 1;
    push_down(rt);
    if(qr <= mid)
        return query(rt<<1, l, mid, ql, qr);
    if(ql > mid)
        return query(rt<<1|1, mid+1, r, ql, qr);
    return max(query(rt<<1, l, mid, ql, qr), query(rt<<1|1, mid+1, r, ql, qr));
}

int lca_query(int u, int v)
{
    int ans = -inf;
    while(top[u] != top[v])
    {
        if(dep[top[u]] < dep[top[v]])
            swap(u, v);
        ans = max(ans, query(1, 2, n, tid[top[u]], tid[u]));
        u = fa[top[u]];
    }
    if(u != v)
    {
        if(dep[u] > dep[v])
            swap(u, v);
        ans = max(ans, query(1, 2, n, tid[u]+1, tid[v]));
    }
    return ans;
}

int main()
{
    T = Scan();
    while(T--)
    {
        init();
        n = Scan();
        for(int i = 1; i < n; ++i)
        {
            e[i][0] = Scan(),e[i][1] = Scan(),e[i][2] = Scan();
            addEdge(e[i][0], e[i][1]);
            addEdge(e[i][1], e[i][0]);
        }
        deal();
        while(~scanf("%s", op) && op[0] != 'D')
        {
            a = Scan(),b = Scan();
            if(op[0] == 'C')
                update_1(1, 2, n, tid[e[a][1]], b);
            else if(op[0] == 'N')
                lca_up(a, b);
            else
                printf("%d\n", lca_query(a, b));
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值