답안 #847059

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
847059 2023-09-09T05:28:43 Z eltu0815 Ants and Sugar (JOI22_sugar) C++14
42 / 100
1541 ms 141512 KB
#include <bits/stdc++.h>
#define MAX 500005
#define MOD 998244353
#define INF (ll)(1e18)
#define inf (1987654321)

using namespace std;    
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef complex<long double> cpx;
constexpr long double PI = acos(-1);

int q, L;
int chk[MAX];
pair<int, pii> query[MAX];

struct Node {
    ll v, sum = 0;
    ll dp[2][2];
    ll lz1, lz2;
    Node() {
        v = sum = 0;
        dp[0][0] = dp[1][0] = dp[0][1] = dp[1][1] = -INF;
        lz1 = lz2 = 0;
    }
};

Node Merge(Node l, Node r) {
    Node ret = Node(); ret.v = r.v; ret.sum = l.sum + r.sum;
    for(int i = 0; i <= 1; ++i) for(int j = 0; j <= 1; ++j) {
        if(i == 0) ret.dp[i][j] = max(ret.dp[i][j], max(r.dp[0][j], r.dp[1][j]));
        if(j == 0) ret.dp[i][j] = max(ret.dp[i][j], max(l.dp[i][0], l.dp[i][1]));
        
        // dp[0][0] of leaf nodes means INF - (lazy updates of lz1), which indicates the number of sugar in the i-th coordinate
        // we have to merge sets that satisfy |S| > 0, but we can also merge the set |S| == 0 and the set |S| > 0 together
        // note that the set whose |S| is 0 always 
        // when there's no ant in the left node, we can make dp[1][i] = -(the number of sugar) + r.dp[1][i] = -l.dp[0][0] + INF + r.dp[1][i];
        if(i == 1) ret.dp[i][j] = max(ret.dp[i][j], l.sum + r.dp[1][j] + l.v);
        if(j == 1) ret.dp[i][j] = max(ret.dp[i][j], l.dp[i][1] + r.sum + l.v);
        
        for(int a = 0; a <= 1; ++a) for(int b = 0; b <= 1; ++b) {
            ret.dp[i][j] = max(ret.dp[i][j], l.dp[i][a] + r.dp[b][j] + (a & b) * l.v);
        }
    }
    return ret;
}

Node seg[MAX << 2];
void init(int str, int ed, int node) {
    if(str == ed) return;
    int mid = str + ed >> 1;
    init(str, mid, node << 1);
    init(mid + 1, ed, node << 1 | 1);
    seg[node] = Merge(seg[node << 1], seg[node << 1 | 1]);
}

void lazyProp(int str, int ed, int node) {
    if(seg[node].lz1) {
        seg[node].sum += seg[node].lz1;
        for(int i = 0; i <= 1; ++i) for(int j = 0; j <= 1; ++j) seg[node].dp[i][j] += seg[node].lz1;
        if(str != ed) {
            seg[node << 1].lz1 += seg[node].lz1;
            seg[node << 1 | 1].lz1 += seg[node].lz1;
        }
        seg[node].lz1 = 0;
    }
    
    if(seg[node].lz2) {
        seg[node].v += seg[node].lz2;
        if(str != ed) {
            seg[node << 1].lz2 += seg[node].lz2;
            seg[node << 1 | 1].lz2 += seg[node].lz2;
        }
        seg[node].lz2 = 0;
    }
}

void update1(int str, int ed, int left, int right, ll val, int node) {
    lazyProp(str, ed, node);
    if(str > right || ed < left) return;
    if(left <= str && ed <= right) {
        seg[node].lz1 = val;
        lazyProp(str, ed, node);
        return;
    }
    int mid = str + ed >> 1;
    update1(str, mid, left, right, val, node << 1);
    update1(mid + 1, ed, left, right, val, node << 1 | 1);
    seg[node] = Merge(seg[node << 1], seg[node << 1 | 1]);
}

void update2(int str, int ed, int left, int right, ll val, int node) {
    lazyProp(str, ed, node);
    if(str > right || ed < left) return;
    if(left <= str && ed <= right) {
        seg[node].lz2 = val;
        lazyProp(str, ed, node);
        return;
    }
    int mid = str + ed >> 1;
    update2(str, mid, left, right, val, node << 1);
    update2(mid + 1, ed, left, right, val, node << 1 | 1);
    seg[node] = Merge(seg[node << 1], seg[node << 1 | 1]);
}

void update3(int str, int ed, int idx, ll val, int node) {
    lazyProp(str, ed, node);
    if(str > idx || ed < idx) return;
    if(str == ed) {
        seg[node].dp[1][1] += val;
        return;
    }
    int mid = str + ed >> 1;
    update3(str, mid, idx, val, node << 1);
    update3(mid + 1, ed, idx, val, node << 1 | 1);
    seg[node] = Merge(seg[node << 1], seg[node << 1 | 1]);
}

ll max_query(int str, int ed, int node) {
    lazyProp(str, ed, node);
    return max(0ll, max(max(seg[1].dp[0][0], seg[1].dp[1][1]), max(seg[1].dp[0][1], seg[1].dp[1][0])));
}

void print(int str, int ed, int node) {
    lazyProp(str, ed, node);
    cout << str << ' ' << ed << " : " << seg[node].v << ' ' << seg[node].dp[0][0] << ' ' << seg[node].dp[1][0] << ' ' << seg[node].dp[0][1] << ' ' << seg[node].dp[1][1] <<
          ' ' << seg[node].lz1 << ' ' << seg[node].lz2 << endl;
    if(str == ed) return;
    int mid = str + ed >> 1;
    print(str, mid, node << 1);
    print(mid + 1, ed, node << 1 | 1);
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    
    cin >> q >> L;
    for(int i = 1; i <= q; ++i) cin >> query[i].first >> query[i].second.first >> query[i].second.second;
    //for(int i = 1; i <= q; ++i) query[i].first = (i + 1) % 2 + 1, query[i].second.first = rand(), query[i].second.second = rand() + 1;
    //random_shuffle(query + 1, query + q + 1);
    
    vector<int> tmp; tmp.push_back(-1000000005); tmp.push_back(2000000005);
    for(int i = 1; i <= q; ++i) if(query[i].first == 1) tmp.push_back(query[i].second.first);
    sort(tmp.begin(), tmp.end()); tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
    
    int n = tmp.size() - 1;
    init(0, n, 1); ll A = 0, B = 0;
    for(int i = 1; i <= q; ++i) {
        if(query[i].first == 1) {
            int idx = lower_bound(tmp.begin(), tmp.end(), query[i].second.first) - tmp.begin();
            A += query[i].second.second;
            if(chk[idx] == 0) chk[idx] = 1, update3(0, n, idx, 1ll * query[i].second.second + INF, 1);
            else update3(0, n, idx, query[i].second.second, 1);
        }
        else {
            int l = lower_bound(tmp.begin(), tmp.end(), query[i].second.first - L) - tmp.begin();
            int r = upper_bound(tmp.begin(), tmp.end(), query[i].second.first + L) - tmp.begin() - 1;
            //if(l <= r) cout <<"WOW" << l << ' ' << r << ' ' << query[i].second.first - L << ' ' << query[i].second.first + L << ' ' << tmp[l] << ' ' << tmp[r] << endl;
            B += query[i].second.second;
            if(l <= r) update1(0, n, l, r, -query[i].second.second, 1);
            if(l < r) update2(0, n, l, r - 1, query[i].second.second, 1);
        }
//        cout << B << ' ';
        cout << A - max_query(0, n, 1) << '\n';
//        if(i == 10) print(0, n, 1);
    }
    return 0;
}

Compilation message

sugar.cpp: In function 'void init(int, int, int)':
sugar.cpp:52:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   52 |     int mid = str + ed >> 1;
      |               ~~~~^~~~
sugar.cpp: In function 'void update1(int, int, int, int, ll, int)':
sugar.cpp:87:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   87 |     int mid = str + ed >> 1;
      |               ~~~~^~~~
sugar.cpp: In function 'void update2(int, int, int, int, ll, int)':
sugar.cpp:101:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  101 |     int mid = str + ed >> 1;
      |               ~~~~^~~~
sugar.cpp: In function 'void update3(int, int, int, ll, int)':
sugar.cpp:114:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  114 |     int mid = str + ed >> 1;
      |               ~~~~^~~~
sugar.cpp: In function 'void print(int, int, int)':
sugar.cpp:130:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  130 |     int mid = str + ed >> 1;
      |               ~~~~^~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 125648 KB Output is correct
2 Correct 18 ms 125784 KB Output is correct
3 Correct 18 ms 125788 KB Output is correct
4 Correct 17 ms 125776 KB Output is correct
5 Correct 18 ms 125784 KB Output is correct
6 Correct 19 ms 125784 KB Output is correct
7 Incorrect 20 ms 125788 KB Output isn't correct
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 125784 KB Output is correct
2 Correct 17 ms 125784 KB Output is correct
3 Correct 17 ms 125788 KB Output is correct
4 Correct 593 ms 137928 KB Output is correct
5 Correct 404 ms 134608 KB Output is correct
6 Correct 659 ms 139208 KB Output is correct
7 Correct 378 ms 134460 KB Output is correct
8 Correct 848 ms 140672 KB Output is correct
9 Correct 809 ms 141460 KB Output is correct
10 Correct 847 ms 140544 KB Output is correct
11 Correct 839 ms 141512 KB Output is correct
12 Correct 350 ms 132816 KB Output is correct
13 Correct 495 ms 133836 KB Output is correct
14 Correct 834 ms 138048 KB Output is correct
15 Correct 813 ms 137948 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 125776 KB Output is correct
2 Correct 351 ms 132692 KB Output is correct
3 Correct 502 ms 134128 KB Output is correct
4 Correct 865 ms 138220 KB Output is correct
5 Correct 822 ms 137928 KB Output is correct
6 Correct 580 ms 136408 KB Output is correct
7 Correct 48 ms 128112 KB Output is correct
8 Correct 307 ms 132304 KB Output is correct
9 Correct 523 ms 133592 KB Output is correct
10 Correct 846 ms 137676 KB Output is correct
11 Correct 1043 ms 137992 KB Output is correct
12 Correct 948 ms 137936 KB Output is correct
13 Correct 767 ms 137972 KB Output is correct
14 Correct 934 ms 137724 KB Output is correct
15 Correct 551 ms 137420 KB Output is correct
16 Correct 722 ms 137680 KB Output is correct
17 Correct 1178 ms 137756 KB Output is correct
18 Correct 1337 ms 137992 KB Output is correct
19 Correct 1460 ms 138088 KB Output is correct
20 Correct 1398 ms 137732 KB Output is correct
21 Correct 1451 ms 137920 KB Output is correct
22 Correct 1515 ms 137836 KB Output is correct
23 Correct 1541 ms 137924 KB Output is correct
24 Correct 1355 ms 137912 KB Output is correct
25 Correct 1468 ms 137936 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 125648 KB Output is correct
2 Correct 18 ms 125784 KB Output is correct
3 Correct 18 ms 125788 KB Output is correct
4 Correct 17 ms 125776 KB Output is correct
5 Correct 18 ms 125784 KB Output is correct
6 Correct 19 ms 125784 KB Output is correct
7 Incorrect 20 ms 125788 KB Output isn't correct
8 Halted 0 ms 0 KB -