KSGT

来源:互联网 发布:秒杀java实现代码 编辑:程序博客网 时间:2024/06/05 15:36

小学期的第一天

上午,困走Linux的迷宫,熟悉了一遍终端,然而什么也没有记住

下午,恶补Java大作业,听教主吹水,深有感触,摇摆于强上大作业与缓学框架之间

晚上,放弃治疗,回归线段树怀抱

夜半,与嵩神交流,单方面碾压,任重而道远


对着教程呼啦呼啦的乱敲,没有章法,只为熟悉,具体的收获谈不上,只能说会用一些奇奇怪怪的编辑器了?然后,用起Ubuntu来不再同以前那般慌张了

犹记得初识PC^2时,小鹿乱撞,好似初恋,想上而不敢


假装学习一下午,开启1w8培训班之路

找到了对口的Java Web实训,然而被前提条件吓到,返回怒补各种框架,从此堕入知识黑洞

期间教主到访,办事间隙吹水赞叹,五年前大弟子发展迅速,超出想象,此番归来惊喜不断
其间更有,我已经培养出这些大弟子,够本了,只要他们隔三差五回来就好。虽为笑语,然亦可从中瞥见教主之得意

这个下午谈了很多,从各自公司变换,Team组成到回来对培养计划的意见,再到我个人的发展,天马行空。


换来换去,选来选去,终于费尽了精力,磨尽了精神。想起来还有个女神等着我约会,赶忙撂下键盘,奔赴现场。然而…这个女神有一点点复杂,懒癌晚期,弃坑而走。本着时刻假装学习的理念,学习了扫描线的写法,发现这只是一个小技巧,并不像原来想象的那样复杂

以我现阶段的认知来说,线段是永远只是线段树,它所能完成只是区间更新/查询,除此之外的任何功能都需要自己来完成,这种扫描线是,上回的二分外壳也是。
因而,线段树本身只完成区间的那部分工作,其他工作由其他部分完成。
队友说,重在建模,有一点模块化封装的意思。

我现在应该是初入线段树了,单点更新/区间更新/扫描线技巧都已经学习,然而对于,线段树的时间复杂度并不能很好的计算,因而做题是只求正确不求时限,超时再说;在构思阶段也无法对具体细节有很好的把握,总是要写到哪儿,编到哪儿,也就是无法把实现落于纸上,造成了编码后面需要大量Debug


现在以POJ 1177 说明存在的问题

对于这道题目,网络上的主流思路在于,离散化,一次扫描更新有扫描线平行的值,于其中更新中断的次数,也就是竖线的条数,完成最终更新

我认为,更新竖线条数的操作过于复杂,需要在segTree当中增加很多的变量,所以才用两次扫描更新,这种写法本应该是快速、简单,然而写孬了。

总共花费 19:00 - 22:30、 23:00 - 00:30、 7:30 - 9: 00

原因在于,建模时,我采用了左闭右闭区间,而这道题目点代表的真的是一个点,而不是一个块(区间?),就造成了,两个段之间的衔接出现了问题
我一直坚持使用CodeBlocks完成这道题目,而CodeBlocks的Debug功能不健全,所以一直没能发现,后面胡乱猜想数据才发现了问题。
教训,在样例出不来的时候,应该尝试简单一些的样例

#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <string>using namespace std;const int maxn = 5000 + 10;struct SegTree{    int l, r, cnt, sum;}segTree[maxn << 2];struct Line{    int a, b, h;    int flag;    Line(int a = 0, int b = 0, int h = 0, int flag = 0)    {        this->a = a, this->b = b, this->h = h, this->flag = flag;    }    bool operator < (const Line & rhs) const    {        return h < rhs.h || h == rhs.h && flag > rhs.flag;    }}hori_line[maxn << 1], vert_line[maxn << 1];int cur1 = 0, cur2 = 0;int new_ab[maxn << 1];int depress(Line * line){    vector<int> pool;    for (int i = 0; i < cur1; i++)    {        pool.push_back(line[i].a);        pool.push_back(line[i].b);    }    sort(pool.begin(), pool.end());    pool.erase(unique(pool.begin(), pool.end()), pool.end());    for (int i = 0; i < cur1; i++)    {        int cur = find(pool.begin(), pool.end(), line[i].a) - pool.begin();        new_ab[cur] = line[i].a; line[i].a = cur;        cur = find(pool.begin(), pool.end(), line[i].b) - pool.begin();        new_ab[cur] = line[i].b; line[i].b = cur;    }    return pool.size() - 1;}void build(int k, int l, int r){    segTree[k].l = l, segTree[k].r = r;    segTree[k].cnt = 0;    segTree[k].sum = 0;    if (l + 1 >= r)    {        return;    }    int m = (l + r) >> 1;    build(k << 1, l, m);    build(k << 1 | 1, m, r);}void update(int k, int l, int r, int c){    if (l > segTree[k].r || r < segTree[k].l) return;    if (l <= segTree[k].l && segTree[k].r <= r)    {        segTree[k].cnt += c;        if (segTree[k].cnt == 0)            segTree[k].sum = segTree[k << 1].sum + segTree[k << 1 | 1].sum;        else            segTree[k].sum = new_ab[segTree[k].r] - new_ab[segTree[k].l];        return;    }    if (segTree[k].l + 1 == segTree[k].r)    {        if (segTree[k].cnt == 0)            segTree[k].sum = 0;        else segTree[k].sum = new_ab[segTree[k].r] - new_ab[segTree[k].l];        return;    }    update(k << 1, l, r, c);    update(k << 1 | 1, l, r, c);    if (segTree[k].cnt == 0)        segTree[k].sum = segTree[k << 1].sum + segTree[k << 1 | 1].sum;}int solve(Line * line){    int w = depress(line);    build(1, 0, w);    int res = 0, pre = 0;    for (int i = 0; i < cur1; i++)    {        update(1, line[i].a, line[i].b, line[i].flag);        int tem = segTree[1].sum;        res += abs(pre - tem);        pre = tem;    }    return res;}int main(){    int n; scanf("%d", &n);    for (int i = 0; i < n; i++)    {        int xx1, yy1, xx2, yy2;        scanf("%d%d%d%d", &xx1, &yy1, &xx2, &yy2);        hori_line[cur1++] = Line(xx1, xx2, yy1, 1);        hori_line[cur1++] = Line(xx1, xx2, yy2, -1);        vert_line[cur2++] = Line(yy1, yy2, xx1, 1);        vert_line[cur2++] = Line(yy1, yy2, xx2, -1);    }    sort(hori_line, hori_line + cur1);    sort(vert_line, vert_line + cur2);    int ans = 0;    ans += solve(hori_line);    //cout << ans << "++++++\n";    ans += solve(vert_line);    //cout << ans << "++++++\n";    printf("%d\n", ans);    return 0;}

代码总体来说是合理的,逻辑简单而清晰

唯一不足之处在于,对sum进行更新,需要对cnt的不同情况进行分类,我没能把它单独放入一个函数中
我认为这个原因在于一开始没能想到这个细节,这个补充都是后面以及Debug的时候补上的,造成了逻辑有一点混乱


教主要我增加深度,正符合我试水操作系统的打算,咨询了一下嵩神,推荐了MIT课程,半夜翻墙出去,了解了大体情况,全英文课程,难度超群,紧张起来了