# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
298767 | Pro_ktmr | Monochrome Points (JOI20_monochrome) | C++14 | 2062 ms | 262540 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#pragma GCC target ("avx2")
#pragma GCC optimize ("unroll-loops")
#pragma GCC optimize ("O3")
#include "bits/stdc++.h"
#include <unordered_set>
#include <unordered_map>
#include <random>
using namespace std;
typedef long long ll;
const ll MOD = 1'000'000'007LL; /*998'244'353LL;*/
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int (i)=0; (i)<(n); (i)++)
const int dx[4]={ 1,0,-1,0 };
const int dy[4]={ 0,1,0,-1 };
template<typename T>
struct TreapSet{
private:
struct Node{
T x; // value
int p; // priority
Node* par; // parent
Node* chi[2]; // children
int s; // size of subtree
T m; // minimum value of subtree
Node(T _x, std::mt19937& mt){
x = _x;
p = mt();
par = NULL;
chi[0] = NULL;
chi[1] = NULL;
s = 1;
m = _x;
}
bool operator==(const Node& u){
return x == u.x;
}
bool operator<(const Node& u){
return x < u.x;
}
};
int N;
Node* root;
std::mt19937 mt;
Node* find(T _x){
Node* u = root;
while(u != NULL && u->x != _x){
if(u->x > _x) u = u->chi[0];
else u = u->chi[1];
}
return u;
}
void update(Node* u){
u->s = (u->chi[0] != NULL ? u->chi[0]->s : 0) + (u->chi[1] != NULL ? u->chi[1]->s : 0) + 1;
u->m = u->x;
if(u->chi[0] != NULL && u->chi[0]->m < u->m) u->m = u->chi[0]->m;
if(u->chi[1] != NULL && u->chi[1]->m < u->m) u->m = u->chi[1]->m;
}
void rotateRight(Node* u){
Node* p = u->par;
u->par = p->par;
if(p->par != NULL){
if(p->par->chi[0] == p) p->par->chi[0] = u;
else p->par->chi[1] = u;
}
p->par = u;
p->chi[0] = u->chi[1];
if(u->chi[1] != NULL) u->chi[1]->par = p;
u->chi[1] = p;
update(p);
update(u);
}
void rotateLeft(Node* u){
Node* p = u->par;
u->par = p->par;
if(p->par != NULL){
if(p->par->chi[0] == p) p->par->chi[0] = u;
else p->par->chi[1] = u;
}
p->par = u;
p->chi[1] = u->chi[0];
if(u->chi[0] != NULL) u->chi[0]->par = p;
u->chi[0] = p;
update(p);
update(u);
}
void bubbleUp(Node* u){
while(u->par != NULL && u->par->p > u->p){
if(u->par->chi[0] == u) rotateRight(u);
else rotateLeft(u);
}
if(u->par == NULL) root = u;
}
public:
TreapSet(){
N = 0;
root = NULL;
std::mt19937 mt2(869120);
mt = mt2;
}
void add(T _x){
Node* u = new Node(_x, mt);
if(N == 0){
root = u;
}
else{
Node* p = root;
Node* v = root;
while(v != NULL){
p = v;
p->s++;
if(p->m > _x) p->m = _x;
if(v->x > _x) v = v->chi[0];
else v = v->chi[1];
}
if(p->x > _x){
p->chi[0] = u;
u->par = p;
}
else{
p->chi[1] = u;
u->par = p;
}
bubbleUp(u);
}
N++;
}
int lower_bound(T _x){
Node* u = root;
bool seted = false;
T ret;
while(u != NULL){
if(u->x >= _x && (!seted || u->x < ret)){
ret = u->x;
seted = true;
}
if(u->chi[0] == NULL) u = u->chi[1];
else if(u->chi[1] == NULL) u = u->chi[0];
else if(u->chi[1]->m <= _x) u = u->chi[1];
else{
if(!seted || ret > u->chi[1]->m){
ret = u->chi[1]->m;
seted = true;
}
u = u->chi[0];
}
}
if(!seted) return N;
return index(ret);
}
int index(T _x){
Node* u = root;
int ret = 0;
while(u != NULL && u->x != _x){
if(u->x > _x) u = u->chi[0];
else{
ret += (u->chi[0] != NULL ? u->chi[0]->s : 0) + 1;
u = u->chi[1];
}
}
if(u == NULL) return -1;
if(u->chi[0] != NULL) ret += u->chi[0]->s;
return ret;
}
};
void rotate(vector<pair<int,int>> &v, int idx){
vector<pair<int,int>> ret;
for(int i=idx; i<v.size(); i++) ret.pb(v[idx]);
rep(i, idx) ret.pb(v[i]);
v = ret;
}
void merge(vector<pair<int,int>> &a, vector<pair<int,int>> &b){
int N = a.size() + b.size();
int i = a.size()-1; int j = b.size()-1;
a.resize(N);
for(int k=N-1; k>=0; k--){
if(i == -1){
a[k] = b[j];
j--;
}
else if(j == -1){
a[k] = a[i];
i--;
}
else if(a[i] > b[j]){
a[k] = a[i];
i--;
}
else{
a[k] = b[j];
j--;
}
}
}
int N;
char S[400001];
vector<int> B, W;
ll memo[200000];
ll solve(int i){
if(memo[i] != -1) return memo[i];
vector<pair<int,int>> v, v2;
rep(j, N){
int a = B[j];
int b = W[(i+j)%N];
if(a > b){
v.pb({a, b});
}
else{
v2.pb({b, a});
}
}
rep(j, (int)v2.size()-1){
if(v2[j] > v2[j+1]){
rotate(v2, j+1);
break;
}
}
merge(v, v2);
TreapSet<int> st;
ll tmp = 0;
for(int j=N-1; j>=0; j--){
tmp += st.lower_bound(v[j].first) - st.lower_bound(v[j].second+1);
st.add(v[j].second);
}
return memo[i] = tmp;
}
signed main(){
scanf("%d", &N);
scanf("%s", S);
rep(i, 2*N){
if(S[i] == 'B') B.pb(i);
if(S[i] == 'W') W.pb(i);
}
memset(memo, -1, sizeof(memo));
ll ans = 0;
int v = (N+1) / 2;
int n = 0;
while(v > 0){
ll a1 = solve(n);
ll a2 = solve((n+1)%N);
ans = max({ans,a1,a2});
if(a1 >= a2) n = (n-v+N) % N;
else n = (n+v) % N;
if(v == 1) break;
v = (v+1) / 2;
}
printf("%lld\n", ans);
}
컴파일 시 표준 에러 (stderr) 메시지
# | 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... |