Submission #1179214

#TimeUsernameProblemLanguageResultExecution timeMemory
1179214Zbyszek99Dungeon 3 (JOI21_ho_t5)C++20
100 / 100
502 ms89296 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define ll long long #define ld long double #define ull unsigned long long #define ff first #define ss second #define pii pair<int,int> #define pll pair<long long, long long> #define vi vector<int> #define vl vector<long long> #define pb push_back #define rep(i, b) for(int i = 0; i < (b); ++i) #define rep2(i,a,b) for(int i = a; i <= (b); ++i) #define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c) #define count_bits(x) __builtin_popcountll((x)) #define all(x) (x).begin(),(x).end() #define siz(x) (int)(x).size() #define forall(it,x) for(auto& it:(x)) using namespace __gnu_pbds; using namespace std; typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set; //mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());} //ll rand(ll a, ll b) {return a + (mt() % (b-a+1));} const int INF = 1e9+50; const ll INF_L = 1e18+40; const ll MOD = 1e9+7; struct line { ll a = 0,b = 0; line operator+(const line& other) { return {a+other.a,b+other.b}; } ll operator()(ll u) { return u*a+b; } bool operator<(const line& other) const { return a < other.a; } }; struct query { int l,r; ll u; int ind; bool operator<(const query& other) const { return u < other.u; } }; const int tree_siz = 1024*512-1; int drzewo_A[tree_siz]; int get_max_A(int akt, int p1, int p2, int s1, int s2) { if(p2 < s1 || p1 > s2) return 0; if(p1 >= s1 && p2 <= s2) { return drzewo_A[akt-1]; } return max(get_max_A(akt*2,p1,(p1+p2)/2,s1,s2),get_max_A(akt*2+1,(p1+p2)/2+1,p2,s1,s2)); } void updA(int v) { drzewo_A[v-1] = max(drzewo_A[v*2-1],drzewo_A[v*2]); if(v != 1) updA(v/2); } void changeA(int ind, int x) { drzewo_A[tree_siz/2+ind] = x; updA((tree_siz/2+ind+1)/2); } line ltree[tree_siz]; line get_f(int akt, int p1, int p2, int s1, int s2) { if(p2 < s1 || p1 > s2) return {0,0}; if(p1 >= s1 && p2 <= s2) return ltree[akt-1]; return get_f(akt*2,p1,(p1+p2)/2,s1,s2) + get_f(akt*2+1,(p1+p2)/2+1,p2,s1,s2); } void updl(int v) { ltree[v-1] = ltree[v*2-1] + ltree[v*2]; if(v != 1) updl(v/2); } void change_f(int ind, line f) { ltree[tree_siz/2+ind] = f; updl((tree_siz/2+ind+1)/2); } ll A_pref[200'002]; ll cost[200'002]; int prev_[200'002]; int nxt[200'002]; ll L[200'002]; ll R[200'002]; ll query_ans[200'002]; bool was_intersect[200'002]; int query_T[200'002]; int query_S[200'002]; ll query_U[200'002]; int qu_l[200'002]; int qu_r[200'002]; vector<pair<int,pll>> events_pref[200'002]; vector<pair<int,pll>> events_suf[200'002]; int main() { ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); //random_start(); int n,q; cin >> n >> q; A_pref[0] = 1e9; rep2(i,1,n) { ll a; cin >> a; A_pref[i] = A_pref[i-1] + a; changeA(i,a); } A_pref[n+1] = A_pref[n]; rep2(i,1,n) cin >> cost[i]; stack<int> st; for(int i = n; i >= 0; i--) { while(!st.empty() && cost[st.top()] > cost[i]) { st.pop(); } if(siz(st) == 0) { nxt[i] = n+1; } else { nxt[i] = st.top(); } st.push(i); } st = {}; rep2(i,1,n) { while(!st.empty() && cost[st.top()] >= cost[i]) { st.pop(); } if(siz(st) == 0) { prev_[i] = 0; } else { prev_[i] = st.top(); } st.push(i); } rep2(i,1,n) { if(prev_[i] > 0) L[i] = A_pref[i-1] - A_pref[prev_[i]-1]; else L[i] = 1e18; R[i] = A_pref[nxt[i]-1] - A_pref[i-1]; } vector<pair<ll,pair<int,line>>> events; rep2(i,1,n) { if(L[i] < R[i]) { events.pb({0,{i,{cost[i],0}}}); events.pb({L[i],{i,{0,cost[i] * L[i]}}}); events.pb({R[i],{i,{-cost[i],cost[i] * (L[i] + R[i])}}}); events.pb({L[i] + R[i],{i,{0,0}}}); } else if(L[i] > R[i]) { events.pb({0,{i,{cost[i],0}}}); events.pb({R[i],{i,{0,cost[i] * R[i]}}}); events.pb({L[i],{i,{-cost[i],cost[i] * (L[i] + R[i])}}}); events.pb({L[i] + R[i],{i,{0,0}}}); } else { events.pb({0,{i,{cost[i],0}}}); events.pb({R[i],{i,{-cost[i],cost[i] * (L[i] + R[i])}}}); events.pb({L[i] + R[i],{i,{0,0}}}); } } vector<query> qu; rep(qq,q) { int s,t; ll u; cin >> s >> t >> u; query_T[qq] = t-1; query_S[qq] = s; query_U[qq] = u; t--; if(get_max_A(1,0,tree_siz/2,s,t) > u) { query_ans[qq] = -1; continue; } int l = s; int r = t; int u_pref = s; while(l <= r) { int mid = (l+r)/2; if(A_pref[mid-1] - A_pref[s-1] <= u) { u_pref = mid; l = mid+1; } else { r = mid-1; } } l = s; r = t; int u_suf = t; while(l <= r) { int mid = (l+r)/2; // cerr << mid << " " << A_pref[t] - A_pref[mid-1] << " bin\n"; if(A_pref[t] - A_pref[mid-1] <= u) { u_suf = mid; r = mid-1; } else { l = mid+1; } } // cerr << u_pref << " " << u_suf << " pref/suf\n"; // if(u_pref < u_suf) // { // if(u_pref + 1 != u_suf) // { // qu.pb({u_pref+1,u_suf-1,u,qq}); // } // } events_pref[s].pb({qq,{u_pref,u}}); events_suf[u_suf].pb({qq,{t,u}}); } //pref calc: vector<pll> stp; for(int i = n; i >= 1; i--) { while(siz(stp) != 0 && cost[i] < cost[stp.back().ff]) { stp.pop_back(); } if(siz(stp) == 0) { stp.pb({i,0}); } else { stp.pb({i,stp.back().ss + cost[i] * (A_pref[stp.back().ff-1] - A_pref[i-1])}); } forall(it,events_pref[i]) { int ind = it.ff; ll u = it.ss.ss; int l = 0; int r = siz(stp)-1; int ans = 0; while(l <= r) { int mid = (l+r)/2; if(A_pref[stp[mid].ff-1] - A_pref[i-1] <= u && stp[mid].ff <= query_T[ind]) { ans = mid; r = mid-1; } else { l = mid+1; } } query_ans[ind] += stp.back().ss - stp[ans].ss; // cerr << query_ans[ind] << " " << ans << " " << stp[ans].ff << " L_add\n"; qu_l[ind] = stp[ans].ff+1; int v = stp[ans].ff; if(nxt[v] <= query_T[ind] || A_pref[query_T[ind]] - A_pref[v-1] > it.ss.ss) { query_ans[ind] += cost[v] * min(it.ss.ss,A_pref[nxt[v]-1] - A_pref[v-1]); } else { qu_r[ind] = -1; was_intersect[ind] = 1; query_ans[ind] += cost[v] * min(it.ss.ss,A_pref[query_T[ind]] - A_pref[v-1]); } // cerr << query_ans[ind] << " L_add\n"; } } //suf calc vector<int> stc; for(int i = n; i >= 1; i--) { while(siz(stc) != 0 && nxt[i] >= nxt[stc.back()]) { stc.pop_back(); } stc.pb(i); forall(it,events_suf[i]) { if(was_intersect[it.ff]) continue; int l = 0; int r = siz(stc)-1; int ans = 0; while(l <= r) { int mid = (l+r)/2; if(nxt[stc[mid]] > query_T[it.ff]) { ans = mid; l = mid+1; } else { r = mid-1; } } int v = stc[ans]; qu_r[it.ff] = v-1; ll l2 = 0; if(prev_[v] >= query_S[it.ff]) l2 = A_pref[v-1] - A_pref[prev_[v]-1]; else l2 = 1e18; ll r2 = 0; if(nxt[v] <= query_T[it.ff]) r2 = A_pref[nxt[v]-1] - A_pref[v-1]; else r2 = A_pref[query_T[it.ff]] - A_pref[v-1]; // cout << i << " " << l << " " << r << " " << u << " " << ans << " " << max(min(u,r) - max(u-l,0LL),0LL)<< " ans\n"; query_ans[it.ff] += max(min(it.ss.ss,r2) - max(it.ss.ss-l2,0LL),0LL) * cost[v]; // cerr << query_ans[it.ff] << " R_add\n"; } } rep(qq,q) { if(qu_l[qq] <= qu_r[qq]) { qu.pb({qu_l[qq],qu_r[qq],query_U[qq],qq}); // cerr << qu_l[qq] << " " << qu_r[qq] << " qq\n"; } } sort(all(qu)); sort(all(events)); int cur_e = 0; forall(it,qu) { while(cur_e < siz(events) && events[cur_e].ff <= it.u) { change_f(events[cur_e].ss.ff,events[cur_e].ss.ss); cur_e++; } query_ans[it.ind] += get_f(1,0,tree_siz/2,it.l,it.r)(it.u); } rep(i,q) cout << query_ans[i] << "\n"; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...