题意:给你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 ",cnt[i]); 78 79 return 0; 80 }