Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) -- C. Destroying Array (并查集)
2016-10-02 00:37
471 查看
大体题意:
给你n 个数字,告诉你破坏每个数字的顺序,每次破坏后你要求一个线段,使得线段不包含破坏的点,并且线段上的值和最大?
思路:
正着删除感觉不好处理,就反过来求了,相当于从一个空序列往上面添加数值,加一次,求一次线段的最大和,在加之前,我们可以先定义一个变量Max 表示之前的操作所得到的最大线段和,然后和加入后进行比较!
加入某个值后,用了并查集进行处理,令c[i]是 i 这个点的权值,那么先判断i+1的位置,如果有值的话,就把i+1这一系列线段加到i位置上,在判断i-1位置,相当于把位置向小位置上并!
有个坑,自己没有注意到,求和时会爆int,开long long
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
typedef long long ll;
vector<ll>ans;
int a[maxn];
int fa[maxn];
int ord[maxn];
int b[maxn];
ll c[maxn];
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void add(int x,int y){
if (x > y)swap(x,y);
int xx = find(x);
int yy = find(y);
if (xx != yy){
fa[yy] = xx;
}
}
int main(){
int n;
scanf("%d",&n);
memset(b,-1,sizeof b);
for (int i = 0; i <= n; ++i)fa[i] = i;
for (int i = 1; i <= n; ++i){
scanf("%d",&a[i]);
}
for (int i = 1; i <= n; ++i){
scanf("%d",&ord[i]);
}
ans.push_back(0);
ll Max = -1;
for (int i = n; i >= 1; --i){
int pos=ord[i];
b[pos] = a[pos];
ll t;
c[pos] += a[pos];
t = a[pos];
if (b[pos+1] != -1){
add(pos,pos+1);
c[pos] += c[pos+1];
t = c[pos];
}
if (b[pos-1] != -1){
int fa = find(pos-1);
add(fa,pos);
c[fa] += c[pos];
t = c[fa];
}
if (t > Max){
Max = t;
}
ans.push_back(Max);
}
reverse(ans.begin(),ans.end());
int len = ans.size();
for (int i = 1; i < len; ++i){
printf("%I64d\n",ans[i]);
}
// printf("\n");
return 0;
}
C. Destroying Array
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an array consisting of n non-negative integers a1, a2, ..., an.
You are going to destroy integers in the array one by one. Thus, you are given the permutation of integers from 1 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 be 0.
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 first i 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 sum 5 consists
of one integer 5.
Fourth element is destroyed. Array is now 1 3 * * . Segment with maximum sum 4 consists
of two integers 1 3.
First element is destroyed. Array is now * 3 * * . Segment with maximum sum 3 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 to 0.
给你n 个数字,告诉你破坏每个数字的顺序,每次破坏后你要求一个线段,使得线段不包含破坏的点,并且线段上的值和最大?
思路:
正着删除感觉不好处理,就反过来求了,相当于从一个空序列往上面添加数值,加一次,求一次线段的最大和,在加之前,我们可以先定义一个变量Max 表示之前的操作所得到的最大线段和,然后和加入后进行比较!
加入某个值后,用了并查集进行处理,令c[i]是 i 这个点的权值,那么先判断i+1的位置,如果有值的话,就把i+1这一系列线段加到i位置上,在判断i-1位置,相当于把位置向小位置上并!
有个坑,自己没有注意到,求和时会爆int,开long long
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
typedef long long ll;
vector<ll>ans;
int a[maxn];
int fa[maxn];
int ord[maxn];
int b[maxn];
ll c[maxn];
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void add(int x,int y){
if (x > y)swap(x,y);
int xx = find(x);
int yy = find(y);
if (xx != yy){
fa[yy] = xx;
}
}
int main(){
int n;
scanf("%d",&n);
memset(b,-1,sizeof b);
for (int i = 0; i <= n; ++i)fa[i] = i;
for (int i = 1; i <= n; ++i){
scanf("%d",&a[i]);
}
for (int i = 1; i <= n; ++i){
scanf("%d",&ord[i]);
}
ans.push_back(0);
ll Max = -1;
for (int i = n; i >= 1; --i){
int pos=ord[i];
b[pos] = a[pos];
ll t;
c[pos] += a[pos];
t = a[pos];
if (b[pos+1] != -1){
add(pos,pos+1);
c[pos] += c[pos+1];
t = c[pos];
}
if (b[pos-1] != -1){
int fa = find(pos-1);
add(fa,pos);
c[fa] += c[pos];
t = c[fa];
}
if (t > Max){
Max = t;
}
ans.push_back(Max);
}
reverse(ans.begin(),ans.end());
int len = ans.size();
for (int i = 1; i < len; ++i){
printf("%I64d\n",ans[i]);
}
// printf("\n");
return 0;
}
C. Destroying Array
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an array consisting of n non-negative integers a1, a2, ..., an.
You are going to destroy integers in the array one by one. Thus, you are given the permutation of integers from 1 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 be 0.
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 first i 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 sum 5 consists
of one integer 5.
Fourth element is destroyed. Array is now 1 3 * * . Segment with maximum sum 4 consists
of two integers 1 3.
First element is destroyed. Array is now * 3 * * . Segment with maximum sum 3 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 to 0.
相关文章推荐
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) A B C D 水 模拟 并查集 优先队列
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array 带权并查集
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C 并查集
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array 带权并查集
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array(并查集)
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)C. Destroying Array(想法题/并查集)
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)C. Destroying Array(想法题/并查集)
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) A. Broken Clock 水题
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) D. Generating Sets 贪心
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) B. Verse Pattern 水题
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) -- D. Generating Sets(贪心)
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) D. Generating Sets 贪心
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array 双向链表+反向做+优先队列
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array -- 逆向思维
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) D. Generating Sets __ dfs+优先队列+贪心
- 【Intel Code Challenge Elimination Round (Div1 + Div2, combined) C】【正难则反并查集】n数按照次序删除每次删除后最大联通块之和
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) -- A. Broken Clock (贪心)
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) F
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) -- B. Verse Pattern(水题)