https://codeforces.com/problemset/problem/371/D
题意:给一个从上到下容积依次增大的容器,多次操作,给某个容器倒水,如果这个容器满了就会溢出,直到最后一个都满了就溢出到外面。然后途中会多次询问某个容器的体积。
思路:暴力的话是(n*m)的。考虑优化,能不能快速找到实际要倒的那个容器编号呢?比如1号满了就直接找到2号,2号满了直接找到3号,5号满了直接找到6号。这里用并查集优化,当前编号容器满了就和下一个编号的容器用并查集建边,以此类推。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+100;
typedef long long LL;
LL fa[maxn],a[maxn],v[maxn];
LL find(LL x)
{
if(x==fa[x]) return fa[x];
return fa[x]=find(fa[x]);
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n;cin>>n;
for(LL i=1;i<=n;i++) cin>>v[i];
for(LL i=1;i<=n+1;i++) fa[i]=i;
LL q;cin>>q;
while(q--)
{
LL op;cin>>op;
if(op==1)
{
LL k,c;cin>>k>>c;
while(c>0)
{
k=find(k);
if(k>n) break;
if(a[k]+c>=v[k])
{
c-=(v[k]-a[k]);
a[k]=v[k];
fa[find(k)]=find(k+1);
}
else{
a[k]+=c;
c=0;break;
}
}
}
else if(op==2)
{
LL index;cin>>index;
cout<<a[index]<<endl;
}
}
return 0;
}