제출 #1365669

#제출 시각아이디문제언어결과실행 시간메모리
1365669hyyhNafta (COI15_nafta)C++20
100 / 100
490 ms430612 KiB
#include <iostream>
#include <math.h>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <iomanip>
#include <set>
#include <bitset>
#include <unordered_map>

using namespace std;
using ll = long long;
using pii = pair<int,int>;
using piii = tuple<int,int,int>;
#define f first
#define s second
#define endl '\n'
#define all(x) begin(x),end(x)
#define m_p make_pair

int const N = 2e3+10;

int const INF = 1e9+10;

int tb[N][N];
bool vis[N][N];


struct Node{
    int val;
    Node* l;
    Node* r;

    Node() : val(0),l(0),r(0) {}
};

typedef Node* pnode;
int si;

vector<pnode> tree;

void builder(pnode &node,int l,int r){
    node = new Node();
    if(l != r){
        int md = l+(r-l)/2;
        builder(node->l,l,md);
        builder(node->r,md+1,r);
    }
}

void builder(){
    tree.emplace_back(nullptr);
    builder(tree.back(),1,si);
}

void update(pnode &node,pnode time,int l,int r,int idx,int val){
    node = new Node(*time);
    if(l == r && l == idx) node->val += val;
    else if(l > idx || r < idx) return;
    else{
        int md = l+(r-l)/2;
        update(node->l,time->l,l,md,idx,val);
        update(node->r,time->r,md+1,r,idx,val);
        node->val = node->l->val+node->r->val;
    }
}

void update(int time,int idx,int val){
    tree.emplace_back(nullptr);
    update(tree.back(),tree[time],1,si,idx,val);
}

int query(pnode L,pnode R,int l,int r,int ql,int qr){
    if(l >= ql && r <= qr) return R->val-L->val;
    else if(l > qr || r < ql) return 0;
    else{
        int md = l+(r-l)/2;
        int q1 = query(L->l,R->l,l,md,ql,qr);
        int q2 = query(L->r,R->r,md+1,r,ql,qr);
        return q1+q2;
    }
}

int query(int timel,int timer,int ql,int qr){
    return query(tree[timel],tree[timer],1,si,ql,qr);
}

void extend(){
    tree.emplace_back(new Node(*tree.back()));
}

void print(pnode node,int l,int r){
    if(l == r) cout << node->val << " ";
    else{
        int md = l+(r-l)/2;
        print(node->l,l,md);
        print(node->r,md+1,r);
    }
}

void print(int time){
    print(tree[time],1,si);
    cout << endl;
}

struct INFO{
    int sum = 0;
    int minpos = 0;
    int maxpos = 0;
};

bool comp(INFO const &a,INFO const &b){
    return a.minpos < b.minpos;
}

vector<INFO> vc;
vector<pii> mov = {{0,1},{1,0},{0,-1},{-1,0}};
vector<int> pos = {0};

INFO cur;

int r,c;

int dp[N][N];

int dp2[N][N];

void dfs(int i,int j){
    cur.sum += tb[i][j];
    cur.minpos = min(cur.minpos,j);
    cur.maxpos = max(cur.maxpos,j);
    for(auto [a,b]:mov){
        int ny = i+a;
        int nx = j+b;
        if(ny <= 0 || ny > r) continue; 
        if(nx <= 0 || nx > c) continue;
        if(vis[ny][nx]) continue;
        if(tb[ny][nx] == -1) continue;
        vis[ny][nx] = 1;
        dfs(ny,nx);
    }
}

int cost(int l,int r){
    if(dp2[l][r] != -1) return dp2[l][r];
    return dp2[l][r] = query(pos[l],pos[r],r,si);
}

void dvc(int i,int l,int r,int rl,int rr){
    pii best = {-INF,-1};
    int md = l+(r-l)/2;
    for(int j{rl};j <= min(md,rr);j++){
        int val = dp[i-1][j]+cost(j,md);
        best = max(best,{val,j});
    }
    dp[i][md] = best.f;
    if(l == r) return;
    dvc(i,l,md,rl,best.s);
    dvc(i,md+1,r,best.s,rr);
}

int main(){
    memset(dp2,-1,sizeof dp2);
    ios_base::sync_with_stdio(0);cin.tie(0);
    cin >> r;
    cin >> c;
    si = c;
    for(int i{1};i <= r;i++){
        for(int j{1};j <= c;j++){
            char ch;cin >> ch;
            if(ch == '.') tb[i][j] = -1;
            else tb[i][j] = ch-'0';
        }
    }
    for(int i{1};i <= r;i++){
        for(int j{1};j <= c;j++){
            if(tb[i][j] == -1 || vis[i][j]) continue;
            vis[i][j] = 1;
            cur.sum = 0;
            cur.minpos = INF;
            cur.maxpos = 0;
            dfs(i,j);
            vc.emplace_back(cur);
        }
    }
    sort(all(vc),comp);
    builder();
    int amo = vc.size();
    int p1 = 0;
    for(int i{1};i <= c;i++){
        while(p1 < amo && vc[p1].minpos <= i){
            update(tree.size()-1,vc[p1].maxpos,vc[p1].sum);
            p1++;
        }
        pos.emplace_back(tree.size()-1);
    }
    // for(int i{1};i <= c;i++){
    //     cout << pos[i] << endl;
    //     print(pos[i]);
    // }
    // cout << cost(1,5) << endl;
    // cout << cost(1,3) << endl;
    for(int i{2};i <= c;i++){
        dp[0][i] = -INF;
    }
    for(int i{1};i <= c;i++){
        dvc(i,1,c,0,c);
        int maxi = 0;
        for(int j{1};j <= c;j++) maxi = max(maxi,dp[i][j]);//, cout << dp[i][j] << " ";
        // cout << endl;
        cout << maxi << endl;
    }
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…