D. Vessels(并查集+模拟)

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;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108625296