2020年“远光杯”粤澳计算机程序设计大赛网络资格赛

捕鱼

看起来像是一个LIS,套个线段树加速一下就可以了。

Trie

稍微卡空间,用数组和map都不行,用vector建图,空间消耗大概减少了10倍。不过要记得sort。

任务安排

为什么要按学生做的时间从大到小排呢?

H题

struct ListNode {
    int next;
    int prev;
    int val;
    int pos;
} ln[10005];

int a[10005];
pii ax[10005];

int Q[10005];
int front, back;

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t;
    scanf("%d", &t);
    for(int ti = 1; ti <= t; ++ti) {
        printf("Case #%d: ", ti);
        int n, x;
        scanf("%d%d", &n, &x);
        ln[0].pos = 0;
        ln[0].next = 1;
        ln[n + 1].pos = n + 1;
        ln[n + 1].prev = n;
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            ln[i].next = i + 1;
            ln[i].prev = i - 1;
            ln[i].pos = i;
            ln[i].val = a[i];
            ax[i] = {a[i], i};
        }
        if(x > n) {
            puts("0");
            continue;
        }
        sort(ax + 1, ax + 1 + n);
        ll sum = 0;
        for(int i = 1; i <= n - x + 1; ++i) {
            int cur0 = ax[i].second;
            int cur1 = cur0;
            for(int cx = x; cx > 1 && ln[cur1].prev != 0; --cx)
                cur1 = ln[cur1].prev;
            int cur2 = cur1;
            front = 1;
            back = 0;
            Q[++back] = ln[cur2].val;
            for(int cx = x; cx > 1; --cx) {
                cur2 = ln[cur2].next;
                while(front <= back && Q[back] < ln[cur2].val)
                    Q[--back];
                Q[++back] = ln[cur2].val;
            }

            int Rlen = (ln[ln[cur2].next].pos - ln[cur2].pos);
            int Llen = (ln[cur1].pos - ln[ln[cur1].prev].pos);
            sum += 1ll * Llen * Rlen * (ax[i].first ^ Q[front]);

            while(ln[cur1].next <= cur0 && ln[cur2].next <= n) {
                if(Q[front] == ln[cur1].val)
                    Q[++front];
                cur1 = ln[cur1].next;
                cur2 = ln[cur2].next;
                while(front <= back && Q[back] < ln[cur2].val)
                    Q[--back];
                Q[++back] = ln[cur2].val;

                int Rlen = (ln[ln[cur2].next].pos - ln[cur2].pos);
                int Llen = (ln[cur1].pos - ln[ln[cur1].prev].pos);
                sum += 1ll * Llen * Rlen * (ax[i].first ^ Q[front]);
            }
            ln[ln[cur0].prev].next = ln[cur0].next;
            ln[ln[cur0].next].prev = ln[cur0].prev;
        }
        printf("%lld
", sum);
    }
    return 0;
}

为什么要是while(ln[cur1].next <= cur0 && ln[cur2].next <= n)而不能是while(cur1 < cur0 && cur2 < n)呢?

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12775295.html