Submission #1230218

#TimeUsernameProblemLanguageResultExecution timeMemory
1230218pumkinheadFeast (NOI19_feast)C++20
100 / 100
86 ms17580 KiB
#include <bits/stdc++.h> using namespace std; template<typename T> struct LinkedList; void attemptMergeNext(LinkedList<long long>& list, int ind); template<typename T> struct LinkedList{ int frontInd = -1; int backInd = -1; struct Node{ int next = -1; int prev = -1; int version = 0; T val; Node(){} Node(T val){ this->val = val; } }; vector<Node> nodes; void erase(int ind){ nodes[ind].version++; if(nodes[ind].next != -1){ nodes[nodes[ind].next].prev = nodes[ind].prev; } if(nodes[ind].prev != -1){ nodes[nodes[ind].prev].next = nodes[ind].next; } if(frontInd == ind){ frontInd = nodes[ind].next; } if(backInd == ind){ backInd = nodes[ind].prev; } // if(nodes[ind].prev != -1){ // attemptMergeNext(*this, nodes[ind].prev); // } } void merge(int ind){ nodes[ind].version++; if(nodes[ind].next != -1){ nodes[ind].val += nodes[nodes[ind].next].val; erase(nodes[ind].next); } if(nodes[ind].prev != -1){ nodes[ind].val += nodes[nodes[ind].prev].val; erase(nodes[ind].prev); } } void append(T val){ Node node = Node(val); int ind = nodes.size(); if(backInd == -1){ frontInd = ind; }else{ nodes[backInd].next = ind; node.prev = backInd; } int prevInd = backInd; backInd = ind; nodes.push_back(node); if(prevInd == -1) return; bool shouldMerge = (nodes[ind].val == 0 || nodes[prevInd].val == 0 || (!((nodes[ind].val > 0) ^ (nodes[prevInd].val > 0)))); if(!shouldMerge) return; merge(ind); } T& front(){ return nodes[frontInd].val; } T& back(){ return nodes[backInd].val; } Node get(int ind){ return nodes[ind]; } }; void attemptMergeNext(LinkedList<long long>& list, int ind){ // int nextInd = list.nodes[ind].next; // if(nextInd == -1) return; // bool merge = (list.nodes[ind].val == 0 || list.nodes[nextInd].val == 0 || (!((list.nodes[ind].val > 0) ^ (list.nodes[nextInd].val > 0)))); // if(merge){ // list.mergeNext(ind); // } } long long greedySolve(int n, int k, vector<int> inp){ vector<int> a; for(int i=0; i<n; i++){ if(inp[i] == 0) continue; a.push_back(inp[i]); } if(a.empty()) return 0; n = a.size(); LinkedList<long long> segments; segments.append(a.front()); for(int i=1; i<n; i++){ segments.append(a[i]); } if(segments.front() < 0){ segments.erase(segments.frontInd); } if(segments.frontInd == -1) return 0; if(segments.back() < 0){ segments.erase(segments.backInd); } if(segments.backInd == -1) return 0; long long ans = 0; int segCount = 0; priority_queue<pair<long long, pair<int, int>>> elemsToErase; int ind = segments.frontInd; while(ind != -1){ long long val = segments.get(ind).val; elemsToErase.push({-abs(val), {ind, segments.get(ind).version}}); if(val > 0){ ans += val; segCount++; } ind = segments.get(ind).next; } while(segCount > k){ pair<long long, pair<int, int>> elem = elemsToErase.top(); elemsToErase.pop(); int node = elem.second.first; if(segments.get(node).version != elem.second.second) continue; long long val = segments.get(node).val; ans -= abs(val); bool erase = segments.backInd == node || node == segments.frontInd; segments.merge(node); if(erase){ segments.erase(node); }else{ elemsToErase.push({-abs(segments.get(node).val), {node, segments.get(node).version}}); } segCount--; } return ans; } long long dpSolve(int n, int k, vector<int> a){ vector<vector<long long>> dp[2]; for(int i=0; i<2; i++){ dp[i] = vector<vector<long long>>(n, vector<long long>(k + 1, 0)); } dp[1][0][1] = max(0, a[0]); for(int i=1; i<n; i++){ for(int j=1; j<=k; j++){ dp[0][i][j] = max({dp[0][i][j], dp[0][i-1][j], dp[1][i-1][j]}); dp[1][i][j] = max({dp[1][i][j], dp[0][i-1][j-1] + a[i], dp[1][i-1][j] + a[i]}); } } long long bestAns = 0; for(int i=1; i<=k; i++){ for(int j=0; j<2; j++){ bestAns = max(bestAns, dp[j][n-1][i]); } } return bestAns; } void bruteforce(int t){ mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int successes = 0; for(int j=0; j<t; j++){ uniform_int_distribution<int> nDist(1, 10); int n = nDist(rng); uniform_int_distribution<int> kDist(1, n); int k = kDist(rng); vector<int> a(n); uniform_int_distribution<int> aDist(-10, 10); for(int i=0; i<n; i++){ a[i] = aDist(rng); } int greedyAns = greedySolve(n, k, a); int dpAns = dpSolve(n, k, a); if(greedyAns != dpAns){ cout<<"MISMATCH FOUND!\n"<<n<<" "<<k<<"\n"; for(int i=0; i<n; i++){ cout<<a[i]<<" "; } cout<<"\nExpected: "<<dpAns<<"\nFound: "<<greedyAns<<"\n"<<endl; }else{ successes++; } } double accuracy = (double) successes / t * 100; cout<<accuracy<<"% accuracy"; } int main(){ cin.tie(nullptr); ios_base::sync_with_stdio(false); if(false){ bruteforce(10000); } int n, k; cin>>n>>k; vector<int> a(n); for(int i=0; i<n; i++){ cin>>a[i]; } // if(n <= 2000 || k == 1){ // cout<<dpSolve(n, k, a); // }else{ cout<<greedySolve(n, k, a); // } } /* 3 1 2 -1 3 */ /* */
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...