HDU 6215 Brute Force Sorting(伪双向链表删边)

来源:互联网 发布:mac pro 13寸高清壁纸 编辑:程序博客网 时间:2024/06/05 15:05

题目地址
题意:Beerus想把一个序列排序,但是他不会排序,他只会删除一些点(如果一个数比前一个数小或者比后一个字符大就要把这个字符删掉),为了让最后得到得串是有序的,或者是空字符串。问最后剩下的序列是什么?
思路:因为要与前一个后一个去比较,但是又要进行删除操作,那么很自然的就可以想到用双向链表去实现,但是双向链表要每次都要把空间给释放掉,要不然就会爆内存了,这样的话我们可以用结构体数组去代替链表,用一个next和pre去指向前一个节点在数组中的下标,这样的话就完美解决了删除空间的操作了。然后如果每次都要去遍历当前剩下的串的话可能会有特殊数据导致TLE,我们可以发现除了第一次要遍历整个串,之后的所有删除的都是围绕着前一次删除的节点的左右进行的,因为只有前一次删除了当前数字,才会导致它的前后出现问题,如果一个数字的前后的元素都没有发生改变的话,他要被删除的话早就删除了,不会突然删除的。所有我们就可以发现,用一个queu去存下删除的点,这样的话就让每次从之前删除的点出发就好了,当删除队列中没有元素了,就结束了,输出没有删除的点就好了。

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 100010#define M 1000010//双倍#define LL long long#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;struct node {    int num;    bool flag;//是不是删除了    int next;//后继    int pre;//前驱}num[N];int del[N];//堆栈int main() {    cin.sync_with_stdio(false);    int n, T;    cin >> T;    while (T--) {        cin >> n;        queue<int> q[2];        for (int i = 1; i <= n; i++) {            cin >> num[i].num;            num[i].flag = true;            if (i == 1) num[i].pre = -1;            else num[i].pre = i - 1;            if (i == n) num[i].next = -1;            else num[i].next = i + 1;        }        int top = 0;        for (int i = 1; i <= n; i++) {            int num1 = num[i].pre;            int num2 = num[i].next;            if ((num1 != -1 && num[num1].num > num[i].num) || (num2 != -1 && num[num2].num < num[i].num)) {//相当与跑第一遍                num[i].flag = false;                del[top++] = i;//删除了哪个节点                q[0].push(i);//记录删除了哪个节点            }        }        for (int i = 0; i < top; i++) {            num[num[del[i]].pre].next = num[del[i]].next;//删除节点            num[num[del[i]].next].pre = num[del[i]].pre;        }        top = 0;        int k = 0;        while (!q[k].empty()) {//看看删除了后前后的点会不会删除            while (!q[k].empty()) {                int t = q[k].front();                q[k].pop();                int num1 = num[t].pre;//删除的节点的前驱结点                int num2 = num[t].next;//删除的节点的后继结点                int p1 = num[num1].pre;//删除节点的前驱的现在前驱节点                int p2 = num[num1].next;//删除节点的前驱的现在后继节点                if ((p1 != -1 && num[p1].num > num[num1].num) || (p2 != -1 && num[p2].num < num[num1].num)) {                    if (num[num1].flag) {                        num[num1].flag = false;//删除操作                        del[top++] = num1;                        q[k ^ 1].push(num1);                    }                }                p1 = num[num2].pre;//删除节点的后继的现在前驱节点                p2 = num[num2].next;//删除节点的前驱的现在前驱节点                if ((p1 != -1 && num[p1].num > num[num2].num) || (p2 != -1 && num[p2].num < num[num2].num)) {                    if (num[num2].flag) {                        num[num2].flag = false;//删除操作                        del[top++] = num2;                        q[k ^ 1].push(num2);                    }                }            }            for (int i = 0; i < top; i++) {//把新删除的节点在链中删除掉                num[num[del[i]].pre].next = num[del[i]].next;                num[num[del[i]].next].pre = num[del[i]].pre;            }            top = 0;            k = k ^ 1;        }        int ans = 0;        for (int i = 1; i <= n; i++) {            if (num[i].flag) {                ans++;            }        }        cout << ans << endl;        for (int i = 1; i <= n; i++) {            if (num[i].flag) {                cout << num[i].num << " ";            }        }        cout << endl;    }    return 0;}
原创粉丝点击