제출 #298767

#제출 시각아이디문제언어결과실행 시간메모리
298767Pro_ktmrMonochrome Points (JOI20_monochrome)C++14
35 / 100
2062 ms262540 KiB
#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) 메시지

monochrome.cpp: In function 'void rotate(std::vector<std::pair<int, int> >&, int)':
monochrome.cpp:173:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  173 |     for(int i=idx; i<v.size(); i++) ret.pb(v[idx]);
      |                    ~^~~~~~~~~
monochrome.cpp:14:27: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   14 | #define rep(i, n) for(int (i)=0; (i)<(n); (i)++)
      |                           ^
monochrome.cpp:174:5: note: in expansion of macro 'rep'
  174 |     rep(i, idx) ret.pb(v[i]);
      |     ^~~
monochrome.cpp: In function 'll solve(int)':
monochrome.cpp:14:27: warning: unnecessary parentheses in declaration of 'j' [-Wparentheses]
   14 | #define rep(i, n) for(int (i)=0; (i)<(n); (i)++)
      |                           ^
monochrome.cpp:210:5: note: in expansion of macro 'rep'
  210 |     rep(j, N){
      |     ^~~
monochrome.cpp:14:27: warning: unnecessary parentheses in declaration of 'j' [-Wparentheses]
   14 | #define rep(i, n) for(int (i)=0; (i)<(n); (i)++)
      |                           ^
monochrome.cpp:220:5: note: in expansion of macro 'rep'
  220 |     rep(j, (int)v2.size()-1){
      |     ^~~
monochrome.cpp: In function 'int main()':
monochrome.cpp:14:27: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   14 | #define rep(i, n) for(int (i)=0; (i)<(n); (i)++)
      |                           ^
monochrome.cpp:240:5: note: in expansion of macro 'rep'
  240 |     rep(i, 2*N){
      |     ^~~
monochrome.cpp:238:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  238 |     scanf("%d", &N);
      |     ~~~~~^~~~~~~~~~
monochrome.cpp:239:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  239 |     scanf("%s", S);
      |     ~~~~~^~~~~~~~~
monochrome.cpp: In function 'll solve(int)':
monochrome.cpp:145:27: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
  145 |                 if(!seted || ret > u->chi[1]->m){
      |                    ~~~~~~~^~~~~~~~~~~~~~~~~~~~~
monochrome.cpp:135:11: note: 'ret' was declared here
  135 |         T ret;
      |           ^~~
monochrome.cpp:145:27: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
  145 |                 if(!seted || ret > u->chi[1]->m){
      |                    ~~~~~~~^~~~~~~~~~~~~~~~~~~~~
monochrome.cpp:135:11: note: 'ret' was declared here
  135 |         T ret;
      |           ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...