結果
| 問題 |
No.3050 Prefix Removal
|
| コンテスト | |
| ユーザー |
Andrew8128
|
| 提出日時 | 2025-03-07 22:14:18 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 852 ms / 2,000 ms |
| コード長 | 14,421 bytes |
| コンパイル時間 | 3,024 ms |
| コンパイル使用メモリ | 129,096 KB |
| 実行使用メモリ | 54,124 KB |
| 最終ジャッジ日時 | 2025-03-07 22:14:48 |
| 合計ジャッジ時間 | 28,771 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 55 |
ソースコード
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
typedef long long ll;
const long long linf = 4610000000000000000;
/*
Don't Remove this Comment !!
https://qiita.com/NokonoKotlin/items/c108a603622c03c4c67b
Copyright (c) NokonoKotlin (okoteiyu) 2024.
Released under the MIT license(https://opensource.org/licenses/mit-license.php)
*/
#include<iostream>
#include<cassert>
template<class type_key , class type_value>
class MyMultiSet{
private:
struct SplayNode{
SplayNode *parent = nullptr;// parent node
SplayNode *left = nullptr;// left child
SplayNode *right = nullptr;// left child
type_key Key;// sorted key
type_value Value;// value (sorted if key is same)
type_key Sum_key;// Sum of Key in Subtree
type_value Min_val,Max_val,Sum_val;// Min,Max,Sum of Value in Subtree
int SubTreeSize = 1;// Size of Subtree under this node
private:
bool copied_instance = false;
public:
SplayNode copy(){
assert(copied_instance == false);
SplayNode res = *this;
res.left = nullptr;
res.right = nullptr;
res.parent = nullptr;
res.copied_instance = true;
return res;
}
SplayNode(){}
SplayNode(type_key key_ , type_value val_){
Key = key_;
Value = val_;
update();
}
// rotate ( this node - parent )
void rotate(){
if(this->parent->parent){
if(this->parent == this->parent->parent->left)this->parent->parent->left = this;
else this->parent->parent->right = this;
}
this->parent->eval();
this->eval();
if(this->parent->left == this){
this->parent->left = this->right;
if(this->right)this->right->parent = this->parent;
this->right = this->parent;
this->parent = this->right->parent;
this->right->parent = this;
this->right->update();
}else{
this->parent->right = this->left;
if(this->left)this->left->parent = this->parent;
this->left = this->parent;
this->parent = this->left->parent;
this->left->parent = this;
this->left->update();
}
this->update();
return;
}
// direction of this parent (left or right)
int state(){
if(this->parent == nullptr)return 0;
this->eval();
if(this->parent->left == this)return 1;
else if(this->parent->right == this)return 2;
return 0;
}
// bottom-up splay
void splay(){
while(bool(this->parent)){
if(this->parent->state() == 0){
this->rotate();
break;
}
if( this->parent->state() == this->state() )this->parent->rotate();
else this->rotate();
this->rotate();
}
this->update();
return;
}
// update data member
void update(){
assert(copied_instance == false);
this->eval();
this->SubTreeSize = 1;
this->Sum_key = this->Key;
this->Max_val = this->Sum_val = this->Min_val = this->Value;
// add left child
if(bool(this->left)){
this->left->eval();
this->SubTreeSize += this->left->SubTreeSize;
if(this->left->Min_val < this->Min_val)this->Min_val = this->left->Min_val;
if(this->left->Max_val > this->Max_val)this->Max_val = this->left->Max_val;
this->Sum_key += this->left->Sum_key;
this->Sum_val += this->left->Sum_val;
}
// add right child
if(bool(this->right)){
this->right->eval();
this->SubTreeSize += this->right->SubTreeSize;
if(this->right->Min_val < this->Min_val)this->Min_val = this->right->Min_val;
if(this->right->Max_val > this->Max_val)this->Max_val = this->right->Max_val;
this->Sum_key += this->right->Sum_key;
this->Sum_val += this->right->Sum_val;
}
return;
}
// evaluate Lazy Evaluation
void eval(){
// if it's necessary , write here.
assert(copied_instance == false);
}
};
/*
1. order of node's Key if [paired_compare] is false.
2. lexicographical order of node's (Key ,Value) if [paired_compare] is true.
*/
constexpr bool CompareNode(SplayNode *a , SplayNode *b , bool paired_compare = false){
a->eval();
b->eval();
if(!paired_compare)return a->Key <= b->Key;
else{
if(a->Key < b->Key)return true;
else if(a->Key == b->Key){
if(a->Value <= b-> Value)return true;
else return false;
}else return false;
}
}
// get [index]th node pointer
SplayNode *get_sub(int index , SplayNode *root){
if(root==nullptr)return root;
SplayNode *now = root;
while(true){
now->eval();
int left_size = 0;
if(now->left != nullptr)left_size = now->left->SubTreeSize;
if(index < left_size)now = now->left;
else if(index > left_size){
now = now->right;
index -= left_size+1;
}else break;
}
now->splay();
return now;
}
// merge 2 SplayTrees
SplayNode *merge(SplayNode *leftRoot , SplayNode *rightRoot){
if(leftRoot!=nullptr)leftRoot->update();
if(rightRoot!=nullptr)rightRoot->update();
if(bool(leftRoot ) == false)return rightRoot;
if(bool(rightRoot) == false )return leftRoot;
rightRoot = get_sub(0,rightRoot);
rightRoot->left = leftRoot;
leftRoot->parent = rightRoot;
rightRoot->update();
return rightRoot;
}
// split SplayTree at [leftnum]
std::pair<SplayNode*,SplayNode*> split(int leftnum, SplayNode *root){
if(leftnum<=0)return std::make_pair(nullptr , root);
if(leftnum >= root->SubTreeSize)return std::make_pair(root, nullptr);
root = get_sub(leftnum , root);
SplayNode *leftRoot = root->left;
SplayNode *rightRoot = root;
if(bool(rightRoot))rightRoot->left = nullptr;
if(bool(leftRoot))leftRoot->parent = nullptr;
leftRoot->update();
rightRoot->update();
return std::make_pair(leftRoot,rightRoot);
}
// remove [index]th node
std::pair<SplayNode*,SplayNode*> Delete_sub(int index , SplayNode *root){
if(bool(root) == false)return std::make_pair(root,root);
root = get_sub(index,root);
SplayNode *leftRoot = root->left;
SplayNode *rightRoot = root->right;
if(bool(leftRoot))leftRoot->parent = nullptr;
if(bool(rightRoot))rightRoot->parent = nullptr;
root->left = nullptr;
root->right = nullptr;
root->update();
return std::make_pair(merge(leftRoot,rightRoot) , root );
}
/*
between 2 SplayNodes [A] and [B] , we define following order.
- if [paired_compare] is false,
- [A] [<] [B] represent a order of these Keys.
- [A] [==] [B] represent these Keys are same
- if [paired_compare] is true,
- [A] [<] [B] represent a lexicographical order of these (Key , Value).
- [A] [==] [B] represent these (Key , Value) are same
This function finds the border index [B] which satisfies following.
1. if [lower] is true, for any [i] smaller than [B] , {[i]th node} [<] {[Node] argument}
2. if [lower] is false, for any [i] smaller than [B] , {[i]th node} [<] {[Node] argument} or {[i]th node} [==] {[Node] argument}
*/
std::pair<SplayNode*,int> bound_sub(SplayNode* Node , SplayNode *root , bool lower , bool paired_compare ){
if(bool(root) == false)return std::make_pair(root,0);
SplayNode *now = root;
int res = 0;
Node->update();
while(true){
now->eval();
bool satisfy = CompareNode(now,Node,paired_compare); // upper_bound (now <= Node)
if(lower)satisfy = !CompareNode(Node,now,paired_compare); // lower_bound (now < Node)
if(satisfy){
if(bool(now->right))now = now->right;
else {
res++;
break;
}
}else{
if(bool(now->left))now = now->left;
else break;
}
}
now->splay();
if(bool(now->left))res += now->left->SubTreeSize;
return std::make_pair(now ,res);
}
// insert [NODE]argument into SplayTree (in which nodes are sorted)
SplayNode *insert_sub(SplayNode *NODE , SplayNode *root , bool paired_compare){
NODE->update();
if(bool(root) == false)return NODE;
// find the border index [x] ( [x]th node [<] [NODE] argument ]
root = bound_sub(NODE,root,true,paired_compare).first;
root->eval();
if(!CompareNode(NODE , root , paired_compare)){
if(root->right != nullptr)root->right->parent = NODE;
NODE->right = root->right;
root->right = nullptr;
NODE->left = root;
}else{
if(root->left != nullptr)root->left->parent = NODE;
NODE->left = root->left;
root->left = nullptr;
NODE->right = root;
}
root->parent = NODE;
root->update();
NODE->update();
return NODE;
}
protected:
// root node of this tree
SplayNode *m_Root = nullptr;
// bluff node object (used as temporary node)
SplayNode *m_bluff_object = nullptr;
SplayNode* BluffObject(type_key k , type_value v){
if(m_bluff_object == nullptr)m_bluff_object = new SplayNode(type_key(0),type_value(0));
m_bluff_object->Key = k;
m_bluff_object->Value = v;
return m_bluff_object;
}
// flag of whether node's Values are defined
// (Values might be undefined if we use insert() function)
bool _paired = true;
void release(){while(m_Root != nullptr)this->Delete(0);}
void init(){
m_Root = nullptr;
_paired = true;
}
// pointer of leftmost node
const SplayNode* const begin(){
if(size() == 0)return nullptr;
m_Root = get_sub(0,m_Root);
return m_Root;
}
public:
MyMultiSet(){init();}
~MyMultiSet(){release();}
// don't copy this object
MyMultiSet(const MyMultiSet<type_key,type_value> & x) = delete ;
MyMultiSet& operator = ( const MyMultiSet<type_key,type_value> & x) = delete ;
MyMultiSet ( MyMultiSet<type_key,type_value>&& x){assert(0);}
MyMultiSet& operator = ( MyMultiSet<type_key,type_value>&& x){assert(0);}
// this function makes whole new SplayTree object from [x] argument
void copy(MyMultiSet<type_key,type_value>& x){
if(this->begin() == x.begin())return;
release();
init();
for(int i=0;i<x.size();i++){
SplayNode t=x.get(i);
this->insert_pair(t.Key,t.Value);
}
this->_paired = x._paired;
}
// tree size
int size(){
if(m_Root == nullptr)return 0;
return m_Root->SubTreeSize;
}
// get copy object of [i]th node
SplayNode get(int i){
assert(0 <= i && i < size());
m_Root = get_sub(i,m_Root);
return m_Root->copy();
}
// get copy object node which covers interval [l,r)
// Ex. we can get Sum of Key in [l,r)
SplayNode GetRange(int l , int r){
assert(0 <= l && l < r && r <= size());
std::pair<SplayNode*,SplayNode*> tmp = split(r,m_Root);
SplayNode* rightRoot = tmp.second;
tmp = split(l,tmp.first);// get subtree
SplayNode res = tmp.second->copy();
m_Root = merge(merge(tmp.first,tmp.second),rightRoot);
return res;
}
// insert key_
void insert( type_key key_ ){
_paired = false;// undefined Value was added
m_Root = insert_sub(new SplayNode(key_,type_value(0)) ,m_Root , false);
return;
}
// insert (key_ , value_)
void insert_pair( type_key key_ , type_value val_){
assert(_paired);
m_Root = insert_sub(new SplayNode(key_,val_) ,m_Root,true);
return;
}
// delete [index]th element
void Delete(int index){
assert(0 <= index && index < size());
std::pair<SplayNode*,SplayNode*> tmp = Delete_sub(index,m_Root);
m_Root = tmp.first;
if(tmp.second != nullptr)delete tmp.second;
return;
}
// erase element which has key_ as Key
void erase(type_key key_){
int it = find(key_);
if(it!=-1)Delete(it);
return;
}
// erase element which has (key_,value_) as (Key,Value)
void erase_pair(type_key key_ , type_value val_){
assert(_paired);
int it = find_pair(key_ , val_);
if(it!=-1)Delete(it);
return;
}
// counts nodes which < (x)
int lower_bound(type_key x){
if(size() == 0)return 0;
std::pair<SplayNode*,int> tmp = bound_sub(BluffObject(x,type_value(0)),m_Root,true,false);
m_Root = tmp.first;
return tmp.second;
}
// counts nodes which < (x,y)
int lower_bound_pair(type_key x , type_value y){
assert(_paired);
if(size() == 0)return 0;
std::pair<SplayNode*,int> tmp = bound_sub(BluffObject(x,y),m_Root,true,true);
m_Root = tmp.first;
return tmp.second;
}
// counts nodes which <= (x)
int upper_bound(type_key x){
if(size() == 0)return 0;
std::pair<SplayNode*,int> tmp = bound_sub(BluffObject(x,type_value(0)),m_Root,false,false);
m_Root = tmp.first;
return tmp.second;
}
// counts nodes which <= (x,y)
int upper_bound_pair(type_key x , type_value y){
assert(_paired);
if(size() == 0)return 0;
std::pair<SplayNode*,int> tmp = bound_sub(BluffObject(x,y),m_Root,false,true);
m_Root = tmp.first;
return tmp.second;
}
// find the index [i] which [i]th node has x as Key (if some answer exist,return smallest)
// if no answer is found, return -1
int find(type_key x){
if(size() == 0)return -1;
if(upper_bound(x) - lower_bound(x) <= 0)return -1;
return lower_bound(x);
}
// find the index [i] which [i]th node has (x,y) as (Key,Value) (if some answer exist,return smallest)
// if no answer is found, return -1
int find_pair(type_key x , type_value y){
assert(_paired);
if(size() == 0)return -1;
if(upper_bound_pair(x,y) - lower_bound_pair(x,y) <= 0)return -1;
return lower_bound_pair(x,y);
}
SplayNode back(){assert(size()>0);return get(size()-1);}
SplayNode front(){assert(size()>0);return get(0);}
void pop_back(){assert(size()>0);Delete(size()-1);}
void pop_front(){assert(size()>0);Delete(0);}
SplayNode operator [](int index){return get(index);}
};
int main()
{
ll N, K;
cin >> N >> K;
vector<ll> A(N);
for (int i = 0; i < N; i++)
{
cin >> A[i];
}
MyMultiSet<ll, ll> mms;
ll sum = 0;
ll ans = -linf;
for (int i = 0; i < N; i++)
{
sum += A[i];
if (K-1 <= i)
{
if (K == 1)
{
ans = max(ans, sum);
}
else
{
ans = max(ans, sum * K - mms.GetRange(0, K-1).Sum_key);
}
}
mms.insert(sum);
}
cout << ans << '\n';
return 0;
}
/*
File : ~/yukicoder/526/C.cpp
Date : 2025/03/07
Time : 21:45:15
*/
Andrew8128