codeforces 722 C Destroying Array (逆向思维+并查集 || STL模拟)
2016-11-19 19:37
477 查看
You are given an array consisting of n non-negative integersa1, a2, ..., an.
You are going to destroy integers in the array one by one. Thus, you are given the permutation of integers from1 to
n defining the order elements of the array are destroyed.
After each element is destroyed you have to find out the segment of the array, such that it contains no destroyed elements and the sum of its elements is maximum possible. The sum of elements in the empty segment is considered to be0.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the length of the array.
The second line contains n integers
a1, a2, ..., an (0 ≤ ai ≤ 109).
The third line contains a permutation of integers from
1 to n — the order used to destroy elements.
Output
Print n lines. The
i-th line should contain a single integer — the maximum possible sum of elements on the segment containing no destroyed elements, after firsti operations are performed.
Examples
Input
Output
Input
Output
Input
Output
Note
Consider the first sample:
Third element is destroyed. Array is now 1 3 * 5. Segment with maximum sum5 consists of one integer
5.
Fourth element is destroyed. Array is now 1 3 * * . Segment with maximum sum4 consists of two integers
1 3.
First element is destroyed. Array is now * 3 * * . Segment with maximum sum3 consists of one integer
3.
Last element is destroyed. At this moment there are no valid nonempty segments left in this array, so the answer is equal to0.
题意:
给你n个数,每次摧毁一个,求每摧毁一个的最大连续和(被摧毁的点的两边不连续)。
摧毁位置3:1,3,*,5 max=5
摧毁位置4:1,3,*,* max=4
摧毁位置1:*,3,*,* max=3
摧毁位置2:*,*,*,* max=0
下次遇到摧毁问题,我们可以逆向思维,现附上超时代码
思路:将操作倒着进行,一开始所有数字都没有加入到数组中,然后倒着一个一个加入,更新最大值。
灵活运用STL的做法
用set来存区间,一开始的区间是[1, n],删除一个数后,去掉[1, n]区间,存入[1, b[1]-1]跟[b[1]+1, n]这两个区间。
每去掉一个区间就加上两个区间
用multi_set来存区间和,每次删掉相应的一个区间和,加上两个区间和,然后输出最大值
用set<pair<终点, 起点> >s来存区间和
用set< pair<int,int> > ::iterator it=s.lower_bound(make_pair(b[i],1))找区间
You are going to destroy integers in the array one by one. Thus, you are given the permutation of integers from1 to
n defining the order elements of the array are destroyed.
After each element is destroyed you have to find out the segment of the array, such that it contains no destroyed elements and the sum of its elements is maximum possible. The sum of elements in the empty segment is considered to be0.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the length of the array.
The second line contains n integers
a1, a2, ..., an (0 ≤ ai ≤ 109).
The third line contains a permutation of integers from
1 to n — the order used to destroy elements.
Output
Print n lines. The
i-th line should contain a single integer — the maximum possible sum of elements on the segment containing no destroyed elements, after firsti operations are performed.
Examples
Input
4 1 3 2 5 3 4 1 2
Output
5 4 3 0
Input
5 1 2 3 4 5 4 2 3 5 1
Output
6 5 5 1 0
Input
8 5 5 4 4 6 6 5 5 5 2 8 7 1 3 4 6
Output
18 16 11 8 8 6 6 0
Note
Consider the first sample:
Third element is destroyed. Array is now 1 3 * 5. Segment with maximum sum5 consists of one integer
5.
Fourth element is destroyed. Array is now 1 3 * * . Segment with maximum sum4 consists of two integers
1 3.
First element is destroyed. Array is now * 3 * * . Segment with maximum sum3 consists of one integer
3.
Last element is destroyed. At this moment there are no valid nonempty segments left in this array, so the answer is equal to0.
题意:
给你n个数,每次摧毁一个,求每摧毁一个的最大连续和(被摧毁的点的两边不连续)。
1 3 2 5
摧毁位置3:1,3,*,5 max=5
摧毁位置4:1,3,*,* max=4
摧毁位置1:*,3,*,* max=3
摧毁位置2:*,*,*,* max=0
下次遇到摧毁问题,我们可以逆向思维,现附上超时代码
#include<bits/stdc++.h> using namespace std; set<int>ss; set<int>::iterator it; const int N = 1e5+10; typedef long long ll; int a ,b ; ll pre ; int main() { ios::sync_with_stdio(false); int n,i,j,p,last; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; pre[i]=(ll) pre[i-1]+a[i]; } for(i=1;i<=n;i++) { ll ans=0; last=0; cin>>b[i]; ss.insert(b[i]); for(it=ss.begin();it!=ss.end();it++) { p=*it; ans=max(ans,pre[p-1]-pre[last]); last=p; } ans=max(ans,pre -pre[last]); cout<<ans<<endl; } return 0; }
思路:将操作倒着进行,一开始所有数字都没有加入到数组中,然后倒着一个一个加入,更新最大值。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5+10; int a ,b ,fa ,vis ; ll sum ; stack<ll>s; int find(int x) { int r=x; while(fa[r]!=r) r=fa[r]; int i=x,j; while(i!=r) { j=fa[i]; fa[i]=r; i=j; } return r; } int main() { ios::sync_with_stdio(false); int n,i,j; int x,y,fx,fy; ll ans=0; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; fa[i]=i; sum[i]=a[i]; } for(i=1;i<=n;i++) cin>>b[i]; for(i=n;i>1;i--) { x=b[i]; vis[x]=1; ans=max(ans,(ll)a[x]); y=b[i]-1; if(y>0 && vis[y]) { fx=find(x); fy=find(y); if(fx!=fy) { fa[fx]=fy; sum[fy]+=sum[fx]; ans=max(ans,sum[fy]); } } y=b[i]+1; if(y<=n && vis[y]) { fx=find(x); fy=find(y); if(fx!=fy) { fa[fx]=fy; sum[fy]+=sum[fx]; ans=max(ans,sum[fy]); } } s.push(ans); } while(!s.empty()) { cout<<s.top()<<endl;; s.pop(); } cout<<"0"<<endl; }
灵活运用STL的做法
用set来存区间,一开始的区间是[1, n],删除一个数后,去掉[1, n]区间,存入[1, b[1]-1]跟[b[1]+1, n]这两个区间。
每去掉一个区间就加上两个区间
用multi_set来存区间和,每次删掉相应的一个区间和,加上两个区间和,然后输出最大值
用set<pair<终点, 起点> >s来存区间和
用set< pair<int,int> > ::iterator it=s.lower_bound(make_pair(b[i],1))找区间
#include <bits/stdc++.h> using namespace std; #define ll __int64 const int N=1e5+10; ll sum , a , ans ; int b ; set<pair<int, int> >s; set<pair<int, int> > :: iterator it; multiset<ll>ms; int main(){ int n; scanf("%d", &n); sum[0] = 0; for(int i=1; i<=n; i++) scanf("%I64d", &a[i]), sum[i] = sum[i-1]+a[i]; for(int i=1; i<=n; i++) scanf("%d", &b[i]); s.clear(), ms.clear(); s.insert(make_pair(n, 1)), ms.insert(sum ); for(int i=1; i<=n; i++){ it = s.lower_bound(make_pair(b[i], 1)); int r = it->first, l = it->second; s.erase(*it); s.insert(make_pair(b[i]-1, l)), s.insert(make_pair(r, b[i]+1)); ms.erase(ms.find(sum[r]-sum[l-1])); ms.insert(sum[b[i]-1]-sum[l-1]), ms.insert(sum[r]-sum[b[i]]); multiset<ll>:: reverse_iterator reit = ms.rbegin(); printf("%I64d\n", *reit); } return 0; }
相关文章推荐
- 【codeforces 722C】【逆向思维 离线+并查集】C. Destroying Array 【给你n个数,每次摧毁一个,求每摧毁一个的最大连续和(被摧毁的点的两边不连续)】
- 并查集——Destroying Array(Intel Code Challenge Elimination Round C)
- Codeforces 400D Dima and Bacteria(并查集最短路)
- Codeforces_(A).Array
- CodeForces 25D(并查集)
- codeforces 299 A. Ksusha and Array
- [LCT维护最小生成树 || CDQ分治 || 线段树 并查集 dfs树] Codeforces 603E #334 (Div. 1) E. Pastoral Oddities
- [Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]
- codeforces 445 B DZY Loves Chemistry【并查集】
- codeforces 366D 并查集
- CodeForces 217 A.Ice Skating(并查集)
- Codeforces_(A).Array
- CodeForces 300A Array
- CodeForces - 771A Bear and Friendship Condition (并查集)
- CodeForces 360 B.Levko and Array(二分+dp)
- Codeforces 300A:Array(易错)
- CodeForces 699D—— Fix a Tree(并查集判断环)
- A - Cthulhu CodeForces - 103B (并查集)
- Codeforces 766D 并查集
- 【24.17%】【codeforces 721D】Maxim and Array