이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
// moreflags=grader.cpp
// ...
// I should have figure out this optimization earlier.
#include "seats.h"
#include<vector>
#include<climits>
#include<algorithm>
#if LOCAL
#include<iostream>
#else
#define NDEBUG
#endif
#include<cassert>
struct Tree{
struct T{
int minimum, count;
T operator+(int lazy) const{return {minimum+lazy, count};}
T operator+(T other) const{
if(minimum<other.minimum) return *this;
if(minimum>other.minimum) return other;
return {minimum, count+other.count};
}
};
struct Node{
int lazy;
T data_;
T data() const{return data_+lazy;}
};
std::vector<Node> data;
Tree(){}
Tree(int number): data(number*2){
}
void build(){
for(int node=int(data.size()/2); --node;)
data[node].data_=data[node*2].data()+data[node*2+1].data();
}
// #fixed# note: initial state is inconsistent (counts values of nonleafs are 1)
// (I knew that this will be problematic later...)
void add(int left, int right, int value){
if(left==right) return;
assert(left<right);
left+=int(data.size()/2); right+=int(data.size()/2);
std::array<int, 2> const old{{left, right-1}};
for(; left<right; left>>=1, right>>=1){
if(left&1) data[left++].lazy+=value;
if(right&1) data[--right].lazy+=value;
}
for(auto it: old){
for(it>>=1; it; it>>=1){
data[it].data_=data[it*2].data()+data[it*2+1].data();
}
}
}
int get(){
// operator+ is commutative
auto const d=data[1].data();
assert(d.minimum>=4);
return d.minimum==4 ? d.count: 0;
}
};
struct MyData{
MyData(){}
//int width;
std::vector<std::vector<int>> value; // pos -> time (in 0..H*W), with padded (H*W) values
struct Pos{ int row, col; };
std::vector<Pos> pos; // time -> pos
Tree tree;
template<int factor> void addTree_(Pos minimum, auto handler){
auto const [r, c]=minimum;
std::array<int, 4> times{{
value[r][c],
value[r+1][c],
value[r][c+1],
value[r+1][c+1],
}};
std::sort(begin(times), end(times));
auto const TOP=int(tree.data.size()/2);
assert(times[0]<TOP); handler(times[0], factor);
if(times[1]==TOP) return; handler(times[1], -factor);
if(times[2]==TOP) return; handler(times[2], factor*5);
if(times[3]==TOP) return; handler(times[3], -factor*5);
// 5 is always greater than 4 => impossible
}
template<int factor> void addTreeMemory(Pos minimum){
addTree_<factor>(minimum, [&](int a, int b){ freeMemory[a]+=b; });
}
template<int factor> void addTreeMemoryIndices(Pos minimum){
addTree_<factor>(minimum, [&](int a, int b){ freeMemory[a]+=b; freeIndices.push_back(a); });
}
std::vector<int> freeMemory; // :)
std::vector<int> freeIndices;
MyData(int const H, int const W, std::vector<int> const& R_, std::vector<int> const& C_):
value(H+2, std::vector<int>(W+2, H*W)),
pos(H*W), tree(H*W), freeMemory(H*W)
{
for(int time=0; time<H*W; ++time){
pos[time]={R_[time], C_[time]};
value[R_[time]+1][C_[time]+1]=time;
}
for(int i=0; i<(int)value.size()-1; ++i)
for(int j=0; j<(int)value[0].size()-1; ++j){
addTreeMemory<1>({i, j});
}
int partial{};
assert(freeMemory.size()==tree.data.size()/2);
for(int a=0; a<(int)freeMemory.size(); ++a){
partial+=freeMemory[a]; freeMemory[a]=0;
tree.data[int(tree.data.size()/2)+a]={0, {partial, 1}};
}
tree.build();
}
int swap(int first, int sec){
std::swap(pos[first], pos[sec]);
std::array<std::array<int, 2> /* can be Pos too if it has comparison operators */, 8> minimums{{
{pos[first].row, pos[first].col},
{pos[first].row, pos[first].col+1},
{pos[first].row+1, pos[first].col},
{pos[first].row+1, pos[first].col+1},
{pos[sec].row, pos[sec].col},
{pos[sec].row, pos[sec].col+1},
{pos[sec].row+1, pos[sec].col},
{pos[sec].row+1, pos[sec].col+1},
}};
std::sort(begin(minimums), end(minimums));
auto const last=std::unique(begin(minimums), end(minimums));
std::for_each(minimums.begin(), last, [&](auto it){
addTreeMemoryIndices<-1>({it[0], it[1]});
});
value[pos[first].row+1][pos[first].col+1]=first;
value[pos[sec].row+1][pos[sec].col+1]=sec;
std::for_each(minimums.begin(), last, [&](auto it){
addTreeMemoryIndices<1>({it[0], it[1]});
});
for(auto a: freeIndices) if(auto& l=freeMemory[a]){
tree.add(a, int(tree.data.size()/2), l);
l=0;
}
freeIndices.clear();
return tree.get();
}
} myData;
void give_initial_chart(int H, int W, std::vector<int> R, std::vector<int> C) {
myData=MyData{H, W, std::move(R), std::move(C)};
}
int swap_seats(int a, int b) {
return myData.swap(a, b);
}
컴파일 시 표준 에러 (stderr) 메시지
seats.cpp:76:50: warning: use of 'auto' in parameter declaration only available with '-fconcepts'
76 | template<int factor> void addTree_(Pos minimum, auto handler){
| ^~~~
seats.cpp: In member function 'void MyData::addTree_(MyData::Pos, auto:1)':
seats.cpp:88:3: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
88 | if(times[1]==TOP) return; handler(times[1], -factor);
| ^~
seats.cpp:88:29: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
88 | if(times[1]==TOP) return; handler(times[1], -factor);
| ^~~~~~~
seats.cpp:89:3: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
89 | if(times[2]==TOP) return; handler(times[2], factor*5);
| ^~
seats.cpp:89:29: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
89 | if(times[2]==TOP) return; handler(times[2], factor*5);
| ^~~~~~~
seats.cpp:90:3: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
90 | if(times[3]==TOP) return; handler(times[3], -factor*5);
| ^~
seats.cpp:90:29: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
90 | if(times[3]==TOP) return; handler(times[3], -factor*5);
| ^~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |