Vessels

Codeforces Round #218 (Div. 2) D:http://codeforces.com/problemset/problem/371/D

题意:就是有一些盘子,盘子里可以装水,这些盘子是从上到下一次排开的,然后会有一些操作1,p ,x,表示在第p个盘子里加入水x,如果这个盘子装不下,水就会流向下一个盘子。2 p,表示查询第p个盘子里有多少水。

题解:这一题用到并查集是真的没有想到,也很难想到。水向下流的过程,就相当于儿子找父亲的过程,然后用并查集直接模拟出来,就可以了。具体可以看看代码。一开始,往线段树和树状数组上想,总是想不到解决办法。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=2e5+10;
 7 int f[N],val[N],a[N];
 8 int n,m,t1,t2,t3;
 9 void init(){
10    memset(val,0,sizeof(val));
11    memset(a,0,sizeof(a));
12    for(int i=1;i<=n;i++)
13     f[i]=i;
14 }
15 int Find(int x){
16    int s;
17    for(s=x;s!=f[s];s=f[s]);
18    while(s!=x){
19     int temp=f[x];
20     f[x]=s;
21     x=temp;
22    }
23    return s;
24 }
25 int main(){
26     while(~scanf("%d",&n)){
27          init();
28         for(int i=1;i<=n;i++){
29             scanf("%d",&val[i]);
30             a[i]=val[i];
31         }
32         scanf("%d",&m);
33         for(int i=1;i<=m;i++){
34             scanf("%d%d",&t1,&t2);
35             if(t1==1){
36                 scanf("%d",&t3);
37                 int r=Find(t2);
38                 while(t3>0){
39                     if(val[r]>=t3){
40                         val[r]-=t3;
41                         break;
42                     }
43                     else{
44                         t3-=val[r];
45                         val[r]=0;
46                         int temp=r++;
47                         if(r>n)break;
48                          else r=Find(r);
49                         f[temp]=r;
50                     }
51                 }
52             }
53             else
54                 printf("%d
",a[t2]-val[t2]);
55         }
56     }
57 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3895034.html