2cm

题目戳这

题意:给你n个数,然后是n个顺序,按照后面的顺序把数列的数字去掉,然后计算每个块的和,输出每次去掉数字之后形成的块的最大和。

思路:一开始还想到了树状数组和线段树上去了,然后实在写不出来,然后看到别人的题解才知道是逆向思维,就是反过来想,按照反向的顺序把数字插入进去,然后计算块的和,这样就不会用到树了。

P.S.这道题要用到并查集,然而对并查集并不是很熟,所以,搞了好久······,而且还因为位置的问题搞了好久······

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<string.h>
 4 #include<math.h>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<string>
 8 #include<queue>
 9 #include<map>
10 #include<stack>
11 #include<set>
12 #define ll long long
13 #define maxn 100010
14 #define PI acos(-1.0)    //圆周率
15 const ll INF = 1e18;
16 const int len=30;
17 using namespace std;
18 int n;
19 ll num[maxn];
20 int wei[maxn];
21 ll f[maxn];
22 ll cnt[maxn];
23 ll flag[maxn];
24 ll s[maxn];
25 int find(int x)
26 {
27     if(f[x]!=x)  f[x]=find(f[x]);
28     return f[x];
29 }
30 void add(int x,int y)
31 {
32     int a=find(x);
33     int b=find(y);
34     if(a!=b)
35     {
36         f[a]=b;
37         s[b]+=s[a];
38     }
39 }
40 ll max(int x,int y)
41 {
42     if(x>y)  return x;
43     else  return y;
44 }
45 int main()
46 {
47     scanf("%d",&n);
48     for(int i=0;i<n;i++)
49     {
50         scanf("%I64d",&num[i]);
51         f[i]=i;
52     }
53     int an=0;
54     for(int i=0;i<n;i++)
55     {
56         scanf("%d",&an);
57         wei[i]=an-1;
58     }
59 
60     ll ans=0;
61     for(int i=n-1;i>=0;i--)
62     {
63         flag[wei[i]]=1;
64 
65         s[wei[i]]=num[wei[i]];
66 
67         //cout<<s[wei[i]]<<" ";
68 
69         if(flag[wei[i]+1]&&wei[i]<n-1)  add(wei[i],wei[i]+1);
70         if(flag[wei[i]-1]&&wei[i]>0)  add(wei[i],wei[i]-1);
71 
72         cnt[i]=ans;
73 
74         ans=max(ans,s[find(wei[i])]);
75     }  //cout<<endl;
76 
77     for(int i=0;i<n;i++)  printf("%I64d\n",cnt[i]);
78 
79     return 0;
80 }
View Code

 

posted on 2016-10-09 21:09  2cm  阅读(144)  评论(0编辑  收藏  举报