1. 程式人生 > >水杯 (資料結構作業)

水杯 (資料結構作業)

演算法與資料結構實驗題 12.2  水杯

 

★實驗任務

 

有 n 個水杯如圖所示放置

從上到下,編號由 1 開始一直到 n,容量 ai 也依次增大(ai+1 > ai),如果

i 號杯子存的水超過了它的容量,則會像 i+1 號水杯流,以此類推現在給你兩個操作

操作一: 1 x y 給 x 號杯子加 y 容量的水操作二: 2 x 查詢 x 杯子裡有多少水。

★資料輸入

輸入第一行為一個正整數 n

接下來 n 個元素,表示第 i 個水杯的容量接著輸入操作的個數 q

接下來 q 行操作。

60%的資料 1<=n<=100,1<=ai,y<=100.

100%的資料 1<=n<=100000,1<=ai,y<=1000000000.

★資料輸出

對於每個操作二,輸出對應的值。

 

輸入示例

輸出示例

2

4

5 10

5

6

8

1 1 4

 

2 1

 

1 2 5

 

1 1 4

 

2 1

 

2 2

 

 

乍一看,暴力遍歷,能過九個點。

仔細一想,我們多遍歷了許多已經裝滿水的水杯,把這些水杯拿走就行了(拿不拿走對結果沒影響,已經滿了的水杯,澆了水,也會往下流。不如直接把它拿走)

這是是個並查集,分為兩個集合,澆滿水的集合和未澆滿的集合。我們統計未澆滿的集合就行了,澆滿的做個標記就行了。不停地按順序把澆滿的位置退出未澆滿的集合。

 

#include <cstdio> 
#include <set>
using namespace std;
int cup[100100]={0}; 	// 容量集合 
int a[100100];			//記錄每個水杯當前的水的體積 
int main()
{
	set <int> s;
	int n,q,x,y,t;
	scanf ("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf ("%d",&a[i]);
		s.insert(i);
	}
	scanf ("%d",&q);
	set <int> ::iterator it;
	set <int> ::iterator temp;
	while(q--)
	{
		scanf ("%d %d",&t,&x);
		if (t==1)
		{
			it=s.lower_bound(x);//查詢水杯 
			scanf ("%d",&y);
			while(y>0&&it!=s.end())
			{
				cup[*it]+=y;
				if (cup[*it]>a[*it])
				{
					y=cup[*it]-a[*it];
					cup[*it]=a[*it];
					temp=it;
					temp++;
					s.erase(it);	//刪除這個水杯 
					it=temp;	
				}
				else
					y=0;
			}
		}
		else
		{
			printf ("%d\n",cup[x]);
		}	
	}
	return 0;
}

在來一個標準並查集

#include <cstdio>
#include <cstring>
using namespace std;
int a[1000100];			//容量a 
int s[1000100];			//父親陣列 	集合的根節點時當前節點往後第一個未澆滿的節點 
int cup[1000100];		//實際容量 
void Make_Set(void)		//初始化 
{
	memset(s,-1,sizeof(s));
}
int Find(int x)			//查詢 
{
	if (s[x]<=0)
		return x;
	else
		return (s[x]=Find(s[x]));
}
void Union(int root1,int root2)		//合併
{
	root1=Find(s[root1]);
	root2=Find(s[root2]);
	if (root1==root2)
		return ;
	if (s[root1]<s[root2])
		s[root2]=root1;
	else
	{
		if (s[root1]==s[root2])
			s[root2]--;
		s[root1]=root2;
	}
}
void Plant(int x,int y,int n)	//澆水 
{
	int i=Find(x);
	while (y>0&&i!=n+1)	//澆到地上 || 水澆完了  ,停止迴圈 
	{
		cup[i]+=y;
		if (cup[i]>a[i])
		{
			y=cup[i]-a[i];
			cup[i]=a[i];
			Union(i,i+1); 
			i=Find(i+1);
		}
		else
			y=0;
	}
}
int main()
{
	int x,y,n,q,t;
	scanf ("%d",&n);
	for (int i=1;i<=n;i++)
		scanf ("%d",&a[i]);
	scanf ("%d",&q);
	while (q--)
	{
		scanf ("%d %d",&t,&x);
		if (t==1)
		{
			scanf ("%d",&y);
			Plant(x,y,n);
		}
		else
		{
			printf ("%d\n",cup[x]);
		}
	}
	return 0;
}