• 核心算法:结合「并查集(路径压缩 + 按秩合并)」和「跳跃指针(nxt 数组)」,解决区间合并的超时问题;
  • 核心逻辑:并查集维护连通块的数值和、节点数,支持快速查询平均值;跳跃指针nxt[i]记录连通块右边界的下一个位置,合并时直接跳过整个连通块,避免逐点遍历;
  • 优化目标:将区间合并的时间复杂度从 O (n) 降至 O (α(n))(α 为阿克曼反函数,接近常数),适配 2e5 级别的数据规模。
  • #include<bits/stdc++.h>
    using namespace std;
    using ll=long long;
    const ll N=2e5+5;
    
    struct UF{
        double v;
        UF* root;
        ll rank=0;
        ll cnt=1;
    };
     
    UF a[N];
    ll nxt[N];
     
    UF *Root(UF* a){
        if(a->root!=a){
            a->root=Root(a->root);
        }
        return a->root;
    }
     
    void merge(ll x,ll y){
        UF* rx=Root(&a[x]);
        UF* ry=Root(&a[y]);
        if(rx==ry)return;
     
        if(rx->rank<ry->rank){
            rx->root=ry;
            ry->cnt+=rx->cnt;
            ry->v+=rx->v;
        }else{
            ry->root=rx;
            rx->cnt+=ry->cnt;
            rx->v+=ry->v;
            if(rx->rank==ry->rank){
                rx->rank++;
            }
        }
    }
    
    int main(){
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); // 加速IO
        ll n,m;
        cin>>n>>m;
        for(ll i=1;i<=n;i++){
            cin>>a[i].v;
            a[i].root=&a[i]; // 并查集初始化:根为自身
            nxt[i] = i + 1; // 跳跃指针初始化:单个节点的右边界下一位是i+1
        }
    
        for(ll i=1;i<=m;i++){
            ll op;
            cin>>op;
            if(op==1){
                ll l,r;
                cin>>l>>r;
                ll cur = l;
                // 区间合并:跳跃指针跳过整个连通块,避免逐点遍历
                while(cur <= r){
                    ll block_r = nxt[cur]; // 当前连通块的右边界下一位
                    if(block_r > r) break; // 连通块超出目标区间,终止
                    
                    merge(cur, block_r); // 合并当前块与下一个块
                    nxt[cur] = nxt[block_r]; // 更新跳跃指针,指向合并后新块的右边界
                    cur = block_r; // 处理下一个连通块
                }
            }else if(op==2){
                ll k;
                cin>>k;
                printf("%.9lf\n",Root(&a[k])->v/(double)Root(&a[k])->cnt); // 输出连通块平均值
            }
        }
        return 0;
    }