本题数据量较大,用并查集把移走挡板后联通的几个池子合并成一个连通块,求某个池子的蓄水量,只需向上找其祖宗的值和池子总数即可。(每个连通块中,编号大的池子为编号小的节点的父亲)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=200010;
int p[N],sz[N];
double a[N];
int find(int x)//并查集
{
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}
void add(int u,int v)
{
    int pu=find(u),pv=find(v);
    if(u>v)swap(u,v);
    p[pu]=p[pv];//节点合并
    sz[pv]+=sz[pu];//连通块的数量累计到祖宗节点
    a[pv]+=a[pu];//水池总量累计到祖宗节点
}
signed main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        p[i]=i;
        sz[i]=1;
    }
    while(m--)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            int l,r;
            cin>>l>>r;
            for(int i=find(l);i<r;i=find(i))//其祖宗节点向上连接即可
            {
                add(i,i+1);
            }
        }
        else
        {
            int q;
            cin>>q;
            int t=find(q);
            printf("%.10lf\n",a[t]/sz[t]);//祖宗节点的蓄水量除以此连通块的数量
        }
    }
    return 0;
}