Chgtaxihe's blog Chgtaxihe's blog
首页
练习
算法学习
读书笔记
小玩意

Chgtaxihe

首页
练习
算法学习
读书笔记
小玩意
  • 训练补题
  • Codeforces 刷题计划
  • 概率dp练习
  • dp专题练习
  • 数论练习
  • 搜索专题练习
  • 图论练习
  • 基础字符串练习
  • AtCoder练习
  • 题解们
  • solutions

  • 训练补题

    • 训练补题-个人1
    • 训练补题-个人10
    • 训练补题-个人2
    • 训练补题-个人5
      • Another Longest Increasing Subsequence Problem (SPOJ LIS2)
    • 训练补题-个人6
    • 训练补题-个人8
    • 训练补题-个人9
    • 训练补题-牛客训练赛1
    • 训练补题-牛客训练赛10
    • 训练补题-牛客训练赛2
    • 训练补题-牛客训练赛3
    • 训练补题-牛客训练赛6
    • 训练补题-牛客训练赛6
    • 训练补题-牛客训练赛7
    • 训练补题-牛客训练赛8
    • 训练补题-牛客训练赛9
    • 训练补题-杭电多校10
    • 训练补题-杭电多校2
    • 训练补题-杭电多校3
    • 训练补题-杭电多校6
    • 训练补题-杭电多校9
    • NWERC 2018-训练补题11
    • SpbKOSHP 19-训练补题12
    • Gym102576-训练补题13
    • GCPC2018-训练补题14
    • Gym102202-训练补题15

训练补题-个人5

# 个人排位赛5补题记录

# Another Longest Increasing Subsequence Problem (SPOJ LIS2)

比赛时一眼看出是CDQ分治,结果疯狂Wa4...

赛后不断去翻题解,直接复制别人代码的关键部分都无法AC,debug了将近一个小时~

最后找到了原因:dp[0]没有赋初值1(所有dp[i≠0i\ne 0i=0]都为默认值0),导致计算最长上升子序列时,第0号元素无法对长度作贡献。

AC代码:

#include <bits/stdc++.h>
#define Android ios::sync_with_stdio(false), cin.tie(NULL)
using namespace std;

const int maxn = 1e5 + 1000;

int n, m, unq[maxn], unq_cnt = 0;
int dp[maxn];
struct info{
    int a, b, c;
};

vector<info> infos, tmp, tmp2;

int tag[maxn], fenwik[maxn], cur_time = 0;

void add(int pos, int delta){
    for(int i=pos; i<=unq_cnt+2; i+=(-i)&i){
        if(tag[i] != cur_time) tag[i] = cur_time, fenwik[i] = 0;
        fenwik[i] = max(delta, fenwik[i]);
    }
}

int query(int pos){
    int ret = 0;
    for(int i=pos; i>0; i-=(-i)&i){
        if(tag[i] != cur_time) tag[i] = cur_time, fenwik[i] = 0;
        ret = max(ret, fenwik[i]);
    }
    return ret;
}

bool cmp_b(info i1, info i2){
    if(i1.b != i2.b) return i1.b < i2.b;
    return i1.a < i2.a;
}

void cdq(int from, int to){
    if(from == to) return;
    int mid = (from + to) >> 1;
    cdq(from, mid);

    sort(infos.begin() + from, infos.begin() + mid + 1, cmp_b);

    for(int i=mid + 1; i<=to; i++) tmp[i] = infos[i];
    sort(tmp.begin() + mid + 1, tmp.begin() + to + 1, cmp_b);

    cur_time++;
    int l = from, r = mid + 1;
    while(l <= mid && r <= to){
        if(infos[l].b < tmp[r].b){
            add(infos[l].c, dp[infos[l].a]);
            l++;
        }else{
            int & ans = dp[tmp[r].a];
            ans = max(ans, query(tmp[r++].c - 1) + 1);
        }
    }
    while(r <= to){
        int & ans = dp[tmp[r].a];
        ans = max(ans, query(tmp[r].c - 1) + 1);
        r++;
    }
    cdq(mid + 1, to);
}

void solve(){
    cin >> n;
    tmp = vector<info>(n);
    infos = vector<info>(n);
    for(int i=0, x, y; i<n; i++){
        cin >> x >> y;
        infos[i] = {i, x, y};
        unq[unq_cnt++] = y;
    }

    sort(unq, unq + unq_cnt);
    unq_cnt = unique(unq, unq + unq_cnt) - unq;
    for(int i=0; i<n; i++){
        infos[i].c = lower_bound(unq, unq + unq_cnt, infos[i].c) - unq + 1;
    }
    dp[0] = 1;
    cdq(0, n - 1);
    int ans = 1;
    for(int i=0; i<n; i++) ans = max(ans, dp[i]);
    cout << ans << '\n';
}

signed main(){
    Android;
    solve();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
上次更新: 2021/02/24, 03:37:30
训练补题-个人2
训练补题-个人6

← 训练补题-个人2 训练补题-个人6→

最近更新
01
深入理解Java虚拟机
03-04
02
DNS工作原理
02-27
03
改用VuePress啦
02-23
更多文章>
Theme by Vdoing | Copyright © 2019-2021
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式