HDU 6215 模拟链表 + 队列优化

来源:互联网 发布:手机淘宝买家秀没有了 编辑:程序博客网 时间:2024/06/06 13:08

简略题意:对一个序列做如下操作:每次同时将一个数,以及这个数右边的比他小的数删除,执行若干次直到整个序列单调不递减。输出最终序列。

假若直接模拟的复杂度是O(n^2)的。
用pre[i]代表与i相连的,在i之前的数。
用suf[i]代表与i相连的,在i之后的数。
其实如果我们需要删除[l,r]区间,那么我们下次有可能删除的只有pre[l],用队列存下这个pre[l],每次删除区间只需要把pre[l]suf[r]连接起来即可。
下次再模拟直接从队列中取数即可。
每个数最多被加入队列1次,并且如果被删除之后就不会再从队列中被访问了。
每个数要么被访问1次,要么被删除,因此时间复杂度为O(n)

#define others#ifdef poj#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#include <string>#endif // poj#ifdef others#include <bits/stdc++.h>#endif // others//#define file#define all(x) x.begin(), x.end()using namespace std;const double eps = 1e-8;int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;};typedef long long LL;namespace solver {    const LL maxn = 100011;    LL cas;    int n;    int v[maxn];    int pre[maxn], suf[maxn];    int q[maxn*10];    void solve() {        scanf("%lld", &cas);        while(cas--) {            scanf("%d", &n);            suf[0] = 1, pre[n+1] = n;            v[0] = -0x3f3f3f3f, v[n+1] = 0x3f3f3f3f;            int head, tail;            head = 1, tail = 0;            for(int i = 1; i <= n; i++) scanf("%d", &v[i]), pre[i] = i - 1, suf[i] = i + 1, q[++tail] = i;            for(;;) {                int cnt = 0;                int tai = 0;                head = 1;                while(head <= tail) {                    int now = q[head];                    int tmp = now;                    int tt = 0;                    while(suf[tmp] <= n && v[tmp] > v[suf[tmp]])                        tt++, tmp = suf[tmp];                    while(q[head] <= tmp && head <= tail) head++;                    if(tt) {                        pre[suf[tmp]] = pre[now];                        suf[pre[now]] = suf[tmp];                        q[++tai] = pre[now];                        cnt+=tt;                    }                }                tail = tai;                if(cnt == 0) break;            }            vector<int> V;            int now = suf[0];            while(now <= n) {                V.push_back(v[now]);                now = suf[now];            }            cout<<V.size()<<endl;            for(int i = 0; i < V.size(); i++)                printf("%d ", V[i]);            puts("");        }    }}int main() {    solver::solve();    return 0;}
原创粉丝点击