Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array -- 逆向思维

  原题中需要求解的是按照它给定的操作次序,即每次删掉一个数字求删掉后每个区间段的和的最大值是多少。

  正面求解需要维护新形成的区间段,以及每段和,需要一些数据结构比如 map 和 set。 map<int, LL>interval2Sum来维护区间段(u->v),mulitset<LL>sum 来维护最大值。那么每次删除操作后,都需要去interval2Sum中找到对应区间,然后erase掉,

重新生成left -> delId -> right两个区间段,最后在maxSum中删掉原有的sum值 ,加入新形成的两短sum。正面刚的话,因为map 和 set的高效性 log级别所以速度还是不错的。(代码转自Codeforces : Ra16bit)

  

#include <bits/stdc++.h>
using namespace std;
int n,i,a,le,ri;
long long s[100100];
map<int, long long> all;
multiset<long long> sum;
int main() {
  scanf("%d",&n);
  for (i=1; i<=n; i++) {
    scanf("%d",&a);
    s[i]=s[i-1]+a;
  }
  all[0]=n;
  sum.insert(-s[n]);
  for (i=1; i<=n; i++) {
    scanf("%d",&a);
    auto it=all.lower_bound(a);
    it--;
    le=it->first;
    ri=it->second;
    sum.erase(sum.find(s[le]-s[ri]));
    all.erase(it);
    if (le+1<a) {
      all[le]=a-1;
      sum.insert(s[le]-s[a-1]);
    }
    if (a<ri) {
      all[a]=ri;
      sum.insert(s[a]-s[ri]);
    }
    if (i==n) puts("0"); else printf("%I64d\n",-*sum.begin());
  }
  return 0;
}

  反向思路,从删掉了最后一个元素开始。一个个恢复。判断左右是否有已经恢复的元素然后在区间内归并元素,用并查集来判断区间所属。那么区间段值不断增大,最后得到结果。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define LL long long
using namespace std;

const int Maxn = 100005;
int n, delId[Maxn], par[Maxn], used[Maxn];
LL a[Maxn], b[Maxn], ans[Maxn];

int find(int x)
{
    return (par[x] == x)?x: find(par[x]);
}

int main()
{
    cin>>n;
    for(int i = 0; i < n; i ++){
        scanf("%lld",&a[i]);
        par[i] = i;
        used[i] = 0;
    }for(int i = 0; i < n; i ++){
        scanf("%d",&delId[i]);
        delId[i] --;
    }
    for(int i = n - 1; i >= 0; i --){
        int index = delId[i];
        used[index] = 1;
        b[index] += a[index];
        if(used[index - 1] && index){
            int fa = find(index - 1);
            b[fa] += a[index];
            par[index] = fa;
        }if(used[index + 1] && index != n - 1){
            int newFa = find(index), oldFa = find(index + 1);
            par[oldFa] = newFa;
            b[newFa] += b[oldFa];
        }
        ans[i] = max(ans[i + 1], b[find(index)]);
    }
    for(int i = 1; i <= n; i ++){
        cout<<ans[i]<<" ";
    }cout<<endl;
    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

41 3 2 53 4 1 2

output

5430

input

51 2 3 4 54 2 3 5 1

output

65510

input

85 5 4 4 6 6 5 55 2 8 7 1 3 4 6

output

18161188660

Note

Consider the first sample:

  1. Third element is destroyed. Array is now 1 3  *  5. Segment with maximum sum 5 consists of one integer 5.
  2. Fourth element is destroyed. Array is now 1 3  *   * . Segment with maximum sum 4 consists of two integers 1 3.
  3. First element is destroyed. Array is now  *  3  *   * . Segment with maximum sum 3 consists of one integer 3.
  4. Last element is destroyed. At this moment there are no valid nonempty segments left in this array, so the answer is equal to 0.
时间: 2024-07-30 20:32:12

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(想法题)

传送门 Description 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 ar

Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)(set容器里count函数以及加强for循环)

题目链接:http://codeforces.com/contest/722/problem/D 1 #include <bits/stdc++.h> 2 #include <iostream> 3 #include <queue> 4 #include <stdio.h> 5 #include <string.h> 6 #include <algorithm> 7 #include <string> 8 #include

Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)

A题,水题,不过我写的时候少考虑了一个细节导致WA了一发. B题,水题,判断一行内元音字母的个数是不是等于p[i]即可. C题,好题,反过来思考,用并查集离线处理.每次如果能合并就合并并更新答案即可.代码如下: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <iostream> 5 #include <queue> 6 using name

C. Destroying Array 并查集/线段树 Intel Code Challenge Elimination Round (Div. 1 + Div. 2, combined)

题目大意就是给一个初始数组,每次删除一个点,问你剩下的连续的那些点中,最大的和是多少 2种做法 第一种是离线并查集  (这里是不会用那个res[]数组,将子的权值挪给父亲那里. 第二种是线段树区间合并.(练手 ///线段树 1 #include <algorithm> 2 #include <stack> 3 #include <istream> 4 #include <stdio.h> 5 #include <map> 6 #include &

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C. Ray Tracing

C. Ray Tracing There are k sensors located in the rectangular room of size n × m meters. The i-th sensor is located at point (xi, yi). All sensors are located at distinct points strictly inside the rectangle. Opposite corners of the room are located

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)

C 模拟 题意:给的是一个矩形,然后√2 的速度走,如果走到边上就正常反射,走到角上,暂停反射,我们知道要不循环要不暂停,记录走到的点最短时间 /************************************************************************* > File Name: c.cpp > Author: opas_chenxin > Mail: [email protected] > Created Time: 2016年10月08日

codeforces Intel Code Challenge Final Round (div.1 + div.2 combined)

比赛水掉3题rk559 rating+115 赛后切掉C n年没打cf了终于又重新变蓝了,果然太弱... 1.A题  Checking the Calendar 给定两个星期几,问是否可能分别是两个月的第一天. 水题暴力枚举月份 #include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<function

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A

Description You are given names of two days of the week. Please, determine whether it is possible that during some non-leap year the first day of some month was equal to the first day of the week you are given, while the first day of the next month w

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)D Dense Subsequence

传送门:D Dense Subsequence 题意:输入一个m,然后输入一个字符串,从字符串中取出一些字符组成一个串,要求满足:在任意长度为m的区间内都至少有一个字符被取到,找出所有可能性中字典序最小的情况,并按字典序输出 思路:字典序 例如 aaaaaaab < ab  也就是说,如果满足要求的取法中取到了b 那么所有的a都应该被取到,这样才可以保证字典序最小,那么也就是说在26个字母中找到一定要被取的最大字母,然后再确定最大的字母的个数,比它小的全部要取 AC代码: 1 #include