Codeforces 371D Vessels【思维+并查集】经典套路题
2017-07-10 17:20
489 查看
D. Vessels
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
There is a system of n vessels arranged one above the other as shown in the figure below. Assume that the vessels are numbered from 1 to
n, in the order from the highest to the lowest, the volume of the
i-th vessel is ai liters.
Initially, all the vessels are empty. In some vessels water is poured. All the water that overflows from the
i-th vessel goes to the
(i + 1)-th one. The liquid that overflows from the
n-th vessel spills on the floor.
Your task is to simulate pouring water into the vessels. To do this, you will need to handle two types of queries:
Add xi liters of water to the
pi-th vessel;
Print the number of liters of water in the ki-th vessel.
When you reply to the second request you can assume that all the water poured up to this point, has already overflown between the vessels.
Input
The first line contains integer n — the number of vessels (1 ≤ n ≤ 2·105). The second line contains
n integers a1, a2, ..., an — the vessels' capacities (1 ≤ ai ≤ 109).
The vessels' capacities do not necessarily increase from the top vessels to the bottom ones (see the second sample). The third line contains integer
m — the number of queries (1 ≤ m ≤ 2·105). Each of the next
m lines contains the description of one query. The query of the first type is represented as "1 pi xi",
the query of the second type is represented as "2 ki" (1 ≤ pi ≤ n,
1 ≤ xi ≤ 109,
1 ≤ ki ≤ n).
Output
For each query, print on a single line the number of liters of water in the corresponding vessel.
Examples
Input
Output
Input
Output
题目大意:
现在有N个杯子,从上到下编号为1~N排列,现在已知每个杯子的容积,现在有两种操作:
①1 x y 在编号为x的杯子中加入容量为y的水、
当这个杯子满了的时候水会向下流到x+1中,如果x+1也满了,那就流到x+2中...............以此类推。
②2 x 查询编号为x的杯子中有多少容积的水 。
思路:
维护一个数组sum【i】表示第i个杯子包含的水的体积。
那么对应我们如果暴力去更新杯子中水的含量的话,时间复杂度最高会达到O(nq);
所以我们考虑优化。
这里不妨考虑将连续序列(都是满状态)的合并成一个集合,使得查询find(i)的结果是第i个杯子之下第一个未满的杯子的编号。
当find(i)这个杯子满了之后,我们将find(i)和find(i)+1合并上,那么再继续考虑在find(i)+1这个杯子上继续加水。依次类推。
更新水量的时候拿并查集跑一下就行了,时间复杂度O(nlogn);
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
int n;
int sum[1500000];
int a[15000000];
int f[15000000];
int find(int a)
{
int r=a;
while(f[r]!=r)
r=f[r];
int i=a;
int j;
while(i!=r)
{
j=f[i];
f[i]=r;
i=j;
}
return r;
}
void merge(int x,int y)
{
int X=find(x);
int Y=find(y);
if(X>Y)
{
f[Y]=X;
}
else f[X]=Y;
}
int main()
{
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i]=i;
}
f[n+1]=n+1;
int q;
scanf("%d",&q);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,have;
scanf("%d%d",&x,&have);
while(have>0)
{
int F=find(x);
if(F==n+1)break;
if(a[F]-sum[F]>=have)
{
sum[F]+=have;
have=0;
}
else
{
have-=a[F]-sum[F];
sum[F]=a[F];
merge(F,F+1);
}
x=F;
}
}
if(op==2)
{
int x;
scanf("%d",&x);
printf("%d\n",sum[x]);
}
}
}
}
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
There is a system of n vessels arranged one above the other as shown in the figure below. Assume that the vessels are numbered from 1 to
n, in the order from the highest to the lowest, the volume of the
i-th vessel is ai liters.
Initially, all the vessels are empty. In some vessels water is poured. All the water that overflows from the
i-th vessel goes to the
(i + 1)-th one. The liquid that overflows from the
n-th vessel spills on the floor.
Your task is to simulate pouring water into the vessels. To do this, you will need to handle two types of queries:
Add xi liters of water to the
pi-th vessel;
Print the number of liters of water in the ki-th vessel.
When you reply to the second request you can assume that all the water poured up to this point, has already overflown between the vessels.
Input
The first line contains integer n — the number of vessels (1 ≤ n ≤ 2·105). The second line contains
n integers a1, a2, ..., an — the vessels' capacities (1 ≤ ai ≤ 109).
The vessels' capacities do not necessarily increase from the top vessels to the bottom ones (see the second sample). The third line contains integer
m — the number of queries (1 ≤ m ≤ 2·105). Each of the next
m lines contains the description of one query. The query of the first type is represented as "1 pi xi",
the query of the second type is represented as "2 ki" (1 ≤ pi ≤ n,
1 ≤ xi ≤ 109,
1 ≤ ki ≤ n).
Output
For each query, print on a single line the number of liters of water in the corresponding vessel.
Examples
Input
2 5 10 6 1 1 4 2 1 1 2 5 1 1 4 2 1 2 2
Output
4 5 8
Input
3 5 10 8 6 1 1 12 2 2 1 1 6 1 3 2 2 2 2 3
Output
7 10 5
题目大意:
现在有N个杯子,从上到下编号为1~N排列,现在已知每个杯子的容积,现在有两种操作:
①1 x y 在编号为x的杯子中加入容量为y的水、
当这个杯子满了的时候水会向下流到x+1中,如果x+1也满了,那就流到x+2中...............以此类推。
②2 x 查询编号为x的杯子中有多少容积的水 。
思路:
维护一个数组sum【i】表示第i个杯子包含的水的体积。
那么对应我们如果暴力去更新杯子中水的含量的话,时间复杂度最高会达到O(nq);
所以我们考虑优化。
这里不妨考虑将连续序列(都是满状态)的合并成一个集合,使得查询find(i)的结果是第i个杯子之下第一个未满的杯子的编号。
当find(i)这个杯子满了之后,我们将find(i)和find(i)+1合并上,那么再继续考虑在find(i)+1这个杯子上继续加水。依次类推。
更新水量的时候拿并查集跑一下就行了,时间复杂度O(nlogn);
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
int n;
int sum[1500000];
int a[15000000];
int f[15000000];
int find(int a)
{
int r=a;
while(f[r]!=r)
r=f[r];
int i=a;
int j;
while(i!=r)
{
j=f[i];
f[i]=r;
i=j;
}
return r;
}
void merge(int x,int y)
{
int X=find(x);
int Y=find(y);
if(X>Y)
{
f[Y]=X;
}
else f[X]=Y;
}
int main()
{
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i]=i;
}
f[n+1]=n+1;
int q;
scanf("%d",&q);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,have;
scanf("%d%d",&x,&have);
while(have>0)
{
int F=find(x);
if(F==n+1)break;
if(a[F]-sum[F]>=have)
{
sum[F]+=have;
have=0;
}
else
{
have-=a[F]-sum[F];
sum[F]=a[F];
merge(F,F+1);
}
x=F;
}
}
if(op==2)
{
int x;
scanf("%d",&x);
printf("%d\n",sum[x]);
}
}
}
}
相关文章推荐
- CodeForces - 859E Desk Disorder 思维 + 并查集判环
- Codeforces 469D Two Sets【思维+并查集】
- Codeforces 828C String Reconstruction【思维+并查集】
- Codeforces 160D Edges in MST【思维+并查集+求桥(有重边)】
- Codeforces 500B:New Year Permutation(并查集||Floyd+思维)
- Codeforces 722C Destroying Array【逆序(离线)思维+并查集】
- codeforces-755【C思维、并查集】
- 【Goodbye2014】Codeforces 500D New Year Santa Network【套路思维题】
- Codeforces 722C(并查集 + 思维)
- CodeForces - 371D Vessels——并查集
- Codeforces 689D Friends and Subsequences【思维+二分+RMQ】套路题
- Codeforces 455E Civilization【思维+树的直径+并查集】
- Codeforces 755C 【并查集】【思维】
- Codeforces 651B Beautiful Paintings【思维】
- codeforces 848A From Y to Y(思维)
- Codeforces-939D:Love Rescue(并查集)
- CodeForces - 731C Socks(并查集,贪心)
- CodeForces 445B DZY Loves Chemistry (并查集)
- 【CodeForces】233B - Non-square Equation(思维)
- CodeForces - 888C K-Dominant Character 思维