E. Merging Towers 线段树区间合并+启发式合并

网上都是并查集的做法,我做的时候想不到,后面看了大佬们的并查集解法,直呼NB。
本孱弱就献上一发线段树区间合并+启发式合并的垃圾解法。
首先,连续的碟子只用一次移动,体现在给出的数组( 碟子属于哪一个圆柱的编号)中为连续的元素相同:
比如: 1 2 3 3 2 4, 需要4次移动,第6个碟子不需要移动,前面第三和第四3 3可以一起移动。
所以用线段树处理出每个区间需要移动的次数,维护左右端点值,如果合并时左区间右端点和右区间左端点相同,说明区间合并时减去一次移动次数。修改时直接单点修改所在圆柱的编号。

合并时采用启发式合并。

总复杂度 O ( N l o g 2 N ) O(Nlog^{2}N) O(Nlog2N)
勉勉强强能过

#include "bits/stdc++.h"
#define lson t<<1,l,mid
#define rson t<<1|1,mid+1,r
using namespace std;
const int N = 2e5+5;

int n,m;
int va[N];

int num[N<<2],lp[N<<2],rp[N<<2];

void pushup(int t){
    int l = t<<1 , r = t<<1|1;
    num[t] = num[l] + num[r];
    if(rp[l]==lp[r]) num[t]--;
    rp[t] = rp[r];
    lp[t] = lp[l];
}

void build(int t,int l,int r){
    if(l==r) {
        num[t] = 1;
        lp[t] = rp[t] = va[l];
        return;
    }
    int mid = (l+r)>>1;
    build(lson);  build(rson);
    pushup(t);
}

void update(int t,int l,int r,int pos,int d){
    if(l==r){
        num[t] = 1;
        lp[t] = rp[t] = d;
        return;
    }
    int mid = (l+r)>>1;
    if(pos<=mid) update(lson,pos,d);
    else update(rson,pos,d);
    pushup(t);
}

vector<vector<int> > v(N);
int id[N];

int main()
{
    ios::sync_with_stdio(false);

    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>va[i];
        id[i] = i;
        v[va[i]].push_back(i);
    }
    build(1,1,n);
    cout<<num[1]-1<<endl;
    for(int i=1;i<m;i++){
        int a,b;  cin>>a>>b;
        int x = id[a] , y = id[b];
        if(v[x].size()<v[y].size()){
            id[a] = y;
            swap(x,y);
        }
        for(int i=0;i<v[y].size();i++){
            v[x].push_back(v[y][i]);
            update(1,1,n,v[y][i],x);
        }
        cout<<num[1]-1<<endl;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值