水杯 (資料結構作業)
阿新 • • 發佈:2018-12-01
演算法與資料結構實驗題 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;
}