首页 > 编程语言 >落谷 R94681591 -- 并查集+离线算法+倒序处理

落谷 R94681591 -- 并查集+离线算法+倒序处理

时间:2022-11-19 20:01:20浏览次数:96  
标签:pre 落谷 int sum 离线 fa add query 倒序

题目描述

树的变迁

思路

因为更改点的权值不会改变树的结构,但是删去一条边会改变树的结构,不同与增加一条边,删除一条边的处理是很麻烦(没实现过!!!)
既然我们无法删除一条边,那么我们可以倒着加边!
这类问题的通用解法是:先保存删边,然后倒叙处理。

犯的错误

1.题目中给定的边的下标从 \(1\) 开始(题目中说的是第 \(k\) 条边,那么 \(k\) 肯定从 \(1\) 开始了),但我代码中边的下标从 \(0\) 开始。不仔细读题的后果)
2.关于节点权值的修改,我们需要一个额外的数组 \(sum\) 来统计树的权值,如果直接在 \(w\) 上修改的话,考虑 \(idx\) 是某个树的 \(root\)(体现在代码中就是并查集的根),如果我们直接修改 \(w[idx]\) ,因为我们的的本意只是修改节点的权值,但是我们把整颗树的权值修改了!那就大错特错了!
3.另外就是由于我们是倒着处理,因此需要倒着输出答案。(倒序处理基本都是需要倒着数处答案的吧!)

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>

using namespace std;

const int N = 1e5 + 10;

int n, m;
int w[N], pre[N], sum[N];
bool st[N];
vector<pair<int,int>> add;
stack<pair<int,pair<int,int>>> query;
stack<int> res;

int find(int x)
{
    if(pre[x] == x) return pre[x];
    return pre[x] = find(pre[x]);
}

void read_init()
{
    for(int i = 0; i < N; i ++ )    pre[i] = i;
    cin >> n >> m;
    for(int i = 1; i <= n; i ++ )   cin >> w[i], sum[i] = w[i];
    for(int i = 0; i < n - 1; i ++ )  {
        int a, b;   cin >> a >> b;
        add.push_back({a,b});
    }
}

void read_query()
{
   for(int i = 0; i < m; i ++ ) {
        int op, a, b;
        cin >> op >> a;
        if(op == 1) { // delete edge
            query.push({1,{a,0}});
            st[a] = true;
        }
        else if(op == 2) { // change edge weight
            cin >> b;
            query.push({2,{a,w[a]}});
            int fa = find(a);
            sum[fa] += b - w[a];
            w[a] = b;
        }
        else { // query weight of tree
            query.push({3,{a,0}});
        }
    } 
}

void add_edge()
{
    for(int i = 0; i < n - 1; i ++ ) {
        if(!st[i + 1]) {
            int a = add[i].first, b = add[i].second;
            int fa = find(a), fb = find(b);
            if(fa != fb) {
                pre[fa] = fb;
                sum[fb] += sum[fa];
            }
        }
    }
}

void solve()
{
    while(query.size()) {
        auto it = query.top();   query.pop();
        int op = it.first, a = it.second.first, b = it.second.second; 
        if(op == 1) { // delete edge
            // now add edge
            int idx = a - 1;
            a = add[idx].first, b = add[idx].second;
            // cout << "a-b: " << a << ' ' << b << endl;
            int fa = find(a), fb = find(b);
            if(fa != fb) {
                pre[fa] = fb;
                sum[fb] += sum[fa];
            }    
        }
        else if(op == 2) { // change edge weight
            int fa = find(a);
            sum[fa] += b - w[a];
            w[a] = b;
        }
        else { // query weight of tree
            res.push(sum[find(a)]);
        }
    }
    while(res.size()) {
        cout << res.top() << endl;
        res.pop();
    }
}

int main()
{
    read_init();
    read_query();
    add_edge();
    solve();
}

标签:pre,落谷,int,sum,离线,fa,add,query,倒序
From: https://www.cnblogs.com/ALaterStart/p/16906885.html

相关文章

  • PaddleOCR(PaddleHub Serving)离线部署包制作
    PaddleOCR(PaddleHubServing)离线部署包制作环境与版本:系统CPU架构Anaconda3PaddlePaddlePaccleOCR银河麒麟ServerV10X86Anaconda3-2021.04-Linux-x86_......
  • Docker离线部署Nginx
    总体思路:在有网络的环境上制作Nginx的镜像包,导出并上传至无网络的环境上,启动Nginx即可。  在上一篇《无网环境DockerRpm离线安装》里面,已经在联网的机器上安装好了......
  • 无网环境Docker Rpm离线安装
    总体思路:找一台可以联网的linux,下载docker的RPM依赖包而不进行安装(yumlocalinstall),将所有依赖的rpm环境打包好,再在无网环境中解压逐一安装(rpm:--force--nodeps)。提前......
  • Docker离线安装使用
    离线安装dockerhttps://www.cnblogs.com/yaoyin/p/16532355.htmldocker离线安装并导入镜像https://blog.csdn.net/m0_67266585/article/details/124174122......
  • Linux centos 在线|离线安装依赖
    离线安装yuminstall--downloadonly--downloaddir=/home/fileszlib-develbzip2-developenssl-develncurses-develepel-releasegccgcc-c++xz-develreadline-de......
  • LCA 之 Tarjan(离线)算法
    \(LCA\)之\(Tarjan\)(离线)算法什么是最近公共祖先?在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先......
  • Windows Server 2016离线安装.NET Framework 3.5
    安装方法:1、下载NetFx3.cab后将其放于C盘WINDOWS文件夹下(C:\Windows)2、点击“开始”找到“WindowsPowerShell”右击“以管理员身份运行”,输入如下命令:dism.exe/onlin......
  • Ubuntu20.04离线安装mysql8.0
    参考网址#1.官网下载对应的文件并解压tar-xfmysql-server_8.0.31-1ubuntu20.04_amd64.deb-bundle.tar#2.下载所需的依赖wgethttp://archive.ubuntu.com/ubuntu/pool......
  • 百度离线地图JS API V3.0
    首先,百度地图JavaScriptAPI3.0版本与2.0版本相比增加了几个小功能,整体没有大的改动,具体可以在官网上查阅。于是就照着先前大佬们分享的2.0离线版本进行3.0版本的制作,附上......
  • 判断NFS服务器挂了或者离线问题
    判断NFS服务器挂了或者离线问题NFS服务器挂了会导致挂载的NFS客户端主机卡顿延迟,或者提示找不到文件因为在执行一些命令的时候会自动去同步,用作同步的NFS服务端挂了,命令......