#include <stdio.h>
#include <strings.h>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <bits/stdc++.h>
#include <tuple>
#include <cstdio>
using namespace std;
typedef unsigned long long ullong;
int main() {
int n, v;
scanf("%d\n", &n);
vector< tuple<int,int> > cities; // (positon, value)
map<int, unsigned int> pos2con; //for the city
map<int, unsigned int> pos2pro; //for the city
map<int, ullong> pos2procum; //total pro so far
map<int, ullong> pos2concum; //total con so far
ullong con_total=0;
ullong pro_total=0;
for (int i=0; i<n; ++i){
scanf("%d", &v);
if (v==0) continue;
if (v>0) {
pro_total += abs(v);
pos2pro[i] = abs(v);
}
if (v<0) {
con_total += abs(v);
pos2con[i] = abs(v);
}
cities.push_back(make_tuple(i, v));
pos2procum[i] = pro_total;
pos2concum[i] = con_total;
}
if (pro_total<con_total) {
cout<<"-1"<<endl;
return 0;
}
//cout<<"n="<<n<<endl;
//for (auto c: cities) cout<<"city: "<<get<0>(c)<<" "<<get<1>(c)<<" "<<pos2procum[get<0>(c)]<<" "<<pos2concum[get<0>(c)]<<endl;
vector< tuple<int,int> > paths; // (len, startix)
for (int i=0; i<cities.size()-1; ++i) {
paths.push_back( make_tuple(get<0>(cities[i+1])-get<0>(cities[i]), i) );
}
sort(paths.begin(), paths.end(), greater< tuple<int,int> >());
//for (auto p: paths) cout<<"path: len="<<get<0>(cities[get<0>(p)])<<" start="<<get<1>(p)<<endl;
ullong total_length = 0;
int firstpos=get<0>(cities.front()), lastpos=get<0>(cities.back());
set<int> breaks = {firstpos, lastpos}, nbreaks = {-firstpos, -lastpos};
for (auto& p: paths) {
int ix=get<1>(p), len=get<0>(p), start=get<0>(cities[ix]), end=start+len;
int le_start = -(*nbreaks.lower_bound(-start));
int ge_end = *breaks.lower_bound(end);
int left_con = pos2concum[start]-pos2concum[le_start]+pos2con[le_start];
int left_pro = pos2procum[start]-pos2procum[le_start]+pos2pro[le_start];
int right_con = pos2concum[ge_end]-pos2concum[end]+pos2con[end];
int right_pro = pos2procum[ge_end]-pos2procum[end]+pos2pro[end];
//cout<<"path: ix="<<ix<<" start="<<start<<" end="<<end<<" le_start="<<le_start<<" ge_end="<<ge_end;
//cout<<" left_con="<<left_con<<" left_pro="<<left_pro<<" right_con="<<right_con<<" right_pro="<<right_pro<<endl;
if (left_pro>=left_con && right_pro>=right_con) { //remove edge
breaks.insert(start); breaks.insert(end);
nbreaks.insert(-start); nbreaks.insert(-end);
//cout<<" -> removed"<<endl;
} else {
total_length += len;
}
}
cout<<total_length<<endl;
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <stdio.h> #include <strings.h> #include <iostream> #include <string> #include <vector> #include <set> #include <map> #include <bits/stdc++.h> #include <tuple> #include <cstdio> using namespace std; typedef unsigned long long ullong; int main() { int n, v; scanf("%d\n", &n); vector< tuple<int,int> > cities; // (positon, value) map<int, unsigned int> pos2con; //for the city map<int, unsigned int> pos2pro; //for the city map<int, ullong> pos2procum; //total pro so far map<int, ullong> pos2concum; //total con so far ullong con_total=0; ullong pro_total=0; for (int i=0; i<n; ++i){ scanf("%d", &v); if (v==0) continue; if (v>0) { pro_total += abs(v); pos2pro[i] = abs(v); } if (v<0) { con_total += abs(v); pos2con[i] = abs(v); } cities.push_back(make_tuple(i, v)); pos2procum[i] = pro_total; pos2concum[i] = con_total; } if (pro_total<con_total) { cout<<"-1"<<endl; return 0; } //cout<<"n="<<n<<endl; //for (auto c: cities) cout<<"city: "<<get<0>(c)<<" "<<get<1>(c)<<" "<<pos2procum[get<0>(c)]<<" "<<pos2concum[get<0>(c)]<<endl; vector< tuple<int,int> > paths; // (len, startix) for (int i=0; i<cities.size()-1; ++i) { paths.push_back( make_tuple(get<0>(cities[i+1])-get<0>(cities[i]), i) ); } sort(paths.begin(), paths.end(), greater< tuple<int,int> >()); //for (auto p: paths) cout<<"path: len="<<get<0>(cities[get<0>(p)])<<" start="<<get<1>(p)<<endl; ullong total_length = 0; int firstpos=get<0>(cities.front()), lastpos=get<0>(cities.back()); set<int> breaks = {firstpos, lastpos}, nbreaks = {-firstpos, -lastpos}; for (auto& p: paths) { int ix=get<1>(p), len=get<0>(p), start=get<0>(cities[ix]), end=start+len; int le_start = -(*nbreaks.lower_bound(-start)); int ge_end = *breaks.lower_bound(end); int left_con = pos2concum[start]-pos2concum[le_start]+pos2con[le_start]; int left_pro = pos2procum[start]-pos2procum[le_start]+pos2pro[le_start]; int right_con = pos2concum[ge_end]-pos2concum[end]+pos2con[end]; int right_pro = pos2procum[ge_end]-pos2procum[end]+pos2pro[end]; //cout<<"path: ix="<<ix<<" start="<<start<<" end="<<end<<" le_start="<<le_start<<" ge_end="<<ge_end; //cout<<" left_con="<<left_con<<" left_pro="<<left_pro<<" right_con="<<right_con<<" right_pro="<<right_pro<<endl; if (left_pro>=left_con && right_pro>=right_con) { //remove edge breaks.insert(start); breaks.insert(end); nbreaks.insert(-start); nbreaks.insert(-end); //cout<<" -> removed"<<endl; } else { total_length += len; } } cout<<total_length<<endl; return 0; } |
English