codeforces 722C Destroying Array 并查集带权

来源:互联网 发布:网络受限制是什么意思 编辑:程序博客网 时间:2024/06/05 01:59

题意:含有n个元素的数组,每次破坏一个数字,每次计算连续的序列元素之和,取出最大值。直到全部破坏为止。

思路:逆向思维,往数组里添数字,每次添加看左右位置是否添加,有连续的就合并,将位置看作要合并的元素,起始时每个位置权值就等于a数组中对应位置的值。

#include<cstdio>#include<cstring>#include<algorithm>#define ll long long#define Max(a,b) (a)>(b)?(a):(b)const int maxn = 1e5+10;using namespace std;ll f[maxn],w[maxn];//带权并查集 ll a[maxn],p[maxn];bool vis[maxn];ll ans[maxn];int Find(int x){if(f[x]==x)return x;else return f[x]=Find(f[x]);}void init(int n){for(int i=1;i<=n;i++)f[i]=i;memset(vis,0,sizeof(vis));}int main(){int n;//freopen("in.txt","r",stdin);while(~scanf("%d",&n)){init(n);for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);for(int i=1;i<=n;i++)scanf("%I64d",&p[i]);ans[n]=0;for(int i=n;i>1;i--)//从最后一个位置开始 {int pos=p[i];w[pos]=a[pos];if(vis[pos-1]){int x=Find(pos);int y=Find(pos-1);f[x]=y;   //将y设为x的父亲结点 w[y]+=w[x];//累加儿子结点权值 }if(vis[pos+1]){int x=Find(pos);int y=Find(pos+1);f[x]=y;w[y]+=w[x];}vis[pos]=1;ans[i-1]=Max(ans[i],w[Find(pos)]);}for(int i=1;i<=n;i++){printf("%I64d\n",ans[i]);}}}

原创粉丝点击