zoukankan      html  css  js  c++  java
  • hdu 6375 百度之星 度度熊学队列

    题目链接

    Problem Description
    度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣。

    初始时有 N 个空的双端队列(编号为 1 到 N ),你要支持度度熊的 Q 次操作。

    ①1 u w val 在编号为 u 的队列里加入一个权值为 val 的元素。(w=0 表示加在最前面,w=1 表示加在最后面)。

    ②2 u w 询问编号为 u 的队列里的某个元素并删除它。( w=0 表示询问并操作最前面的元素,w=1 表示最后面)

    ③3 u v w 把编号为 v 的队列“接在”编号为 u 的队列的最后面。w=0 表示顺序接(队列 v 的开头和队列 u 的结尾连在一起,队列v 的结尾作为新队列的结尾), w=1 表示逆序接(先将队列 v 翻转,再顺序接在队列 u 后面)。且该操作完成后,队列 v 被清空。
    Input
    有多组数据。

    对于每一组数据,第一行读入两个数 N 和 Q。

    接下来有 Q 行,每行 3~4 个数,意义如上。

    N≤150000,Q≤400000

    1≤u,v≤N,0≤w≤1,1≤val≤100000

    所有数据里 Q 的和不超过500000
    Output
    对于每组数据的每一个操作②,输出一行表示答案。

    注意,如果操作②的队列是空的,就输出−1且不执行删除操作。
    Sample Input
    2 10
    1 1 1 23
    1 1 0 233
    2 1 1
    1 2 1 2333
    1 2 1 23333
    3 1 2 1
    2 2 0
    2 1 1
    2 1 0
    2 1 1
    Sample Output
    23
    -1
    2333
    233
    23333
    提示
    由于读入过大,C/C++ 选手建议使用读入优化。
    一个简单的例子:
    void read(int &x){
    char ch = getchar();x = 0;
    for (; ch < '0' || ch > '9'; ch = getchar());
    for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    }
    题意
    实现双向队列,要求的功能有:维护N个双向队列,在首/尾部进行插入/删除,以及将一个队列顺序/逆序附到另一个队列尾部,并且清空原序列。
    分析
    为了避免双向队列颠倒的复杂度,其实完全可以忽略节点的先后顺序,把双向队列想象成一个所有节点入度出度都为1的连通图,那么对链表所有的操作,都可以看作是在图上的加边减边操作,因此,只需要维护每个节点的两条边就行了。
    具体的来说,队列加点=连通图中新增一个节点并连一条边到指定的边界;队列删点=图删边;队列附加=两个连通图之间加一条边,连接两个边界点。
    因为总是在队列首尾操作,也就是图的边界点,因此记录下每个连通图的两个边界,每次只需要找到图上边界点的相邻的点进行操作,并在操作完后,更新连通图的边界点。
    注意
    空队列不能被删除,但可以添加一个非空队列到他的后面

     代码

    #include<stdio.h>
    #include<memory.h>
    int head[150005], tail[150005];
    int n, q;
    int id = 0;
    //双向链表节点
    struct thing
    {
        int v;
        int t1, t2;//不必记录顺序
        thing() :v(0), t1(-1), t2(-1) {}
        void conn(int x) {
            if (t1 == -1)t1 = x;
            else t2 = x;
        }
        void brk(int x) {
            if (t1 == x)t1 = -1;
            else if (t2 == x)t2 = -1;
        }
    }node[400005];
    
    //头部插入
    void qaddf(int qid, int nid) {
        if (head[qid] == -1) {
            head[qid] = nid;
            tail[qid] = nid;
        }
        else {
            int h = head[qid];
            node[nid].conn(h);
            node[h].conn(nid);
            head[qid] = nid;
        }
    }
    
    //尾部插入
    void qadde(int qid, int nid) {
        if (head[qid] == -1) {
            head[qid] = nid;
            tail[qid] = nid;
        }
        else {
            int t = tail[qid];
            node[nid].conn(t);
            node[t].conn(nid);
            tail[qid] = nid;
        }
    }
    
    //头部删除
    int delf(int qid) {
        int s = head[qid];
        if (s == -1)return -1;
    
        if (head[qid] == tail[qid]) {
            head[qid] = -1; tail[qid] = -1;
            return node[s].v;
        }
    
        int next = (node[s].t1 != -1 ? node[s].t1 : node[s].t2);
        node[next].brk(s);
        head[qid] = next;
        return node[s].v;
    }
    
    //尾部删除
    int dele(int qid) {
        int s = tail[qid];
        if (s == -1)return -1;
    
        if (head[qid] == tail[qid]) {
            head[qid] = -1; tail[qid] = -1;
            return node[s].v;
        }
    
        int next = (node[s].t1 != -1 ? node[s].t1 : node[s].t2);
        node[next].brk(s);
        tail[qid] = next;
        return node[s].v;
    }
    
    //顺序连接
    void linkf(int q1, int q2) {
        if (head[q2] == -1)return;
        if (head[q1] != -1) {
            node[tail[q1]].conn(head[q2]);
            node[head[q2]].conn(tail[q1]);
            tail[q1] = tail[q2];
            
        }
        else
        {
            head[q1] = head[q2];
            tail[q1] = tail[q2];
        }
        head[q2] = -1; tail[q2] = -1;
    }
    
    //逆序连接
    void linke(int q1, int q2) {
        if(head[q2]==-1)return;
        if (head[q1] != -1) {
            node[tail[q1]].conn(tail[q2]);
            node[tail[q2]].conn(tail[q1]);
            tail[q1] = head[q2];
            
        }
        else
        {
            tail[q1] = head[q2];
            head[q1] = tail[q2];
        }
        head[q2] = -1; tail[q2] = -1;
    }
    
    //简易读外挂
    void getn(int&x) {
        x = 0;
        char ch;
        do ch = getchar(); while (ch<'0' || ch>'9');
        do { x = x * 10 + ch - '0'; ch = getchar(); } while ('0' <= ch&&ch <= '9');
    }
    
    int main() {
        int ipt[4];
        while (~scanf("%d %d", &n, &q)) {
            id = 0;
            memset(head, -1, sizeof head);
            memset(tail, -1, sizeof tail);
            for (int i = 0; i<q; ++i) {
                getn(ipt[0]);
                switch (ipt[0]) {
                case 1://在队列ipt[1]中插入ipt[3]到头/尾部(ipt[2]=0/1)
                    getn(ipt[1]); getn(ipt[2]); getn(ipt[3]);
                    node[++id].v = ipt[3]; node[id].t1 = -1; node[id].t2 = -1;
                    if (ipt[2] == 0) {
                        qaddf(ipt[1], id);
                    }
                    else {
                        qadde(ipt[1], id);
                    }
                    break;
                case 2://在队列ipt[1]中删除头/尾部(ipt[2]=0/1)
                    getn(ipt[1]); getn(ipt[2]);
                    if (ipt[2] == 0) {
                        printf("%d
    ", delf(ipt[1]));
                    }
                    else {
                        printf("%d
    ", dele(ipt[1]));
                    }
                    break;
                case 3://将队列ipt[2]正/反接到ipt[1]后面(ipt[3]=0/1)
                    getn(ipt[1]); getn(ipt[2]); getn(ipt[3]);
                    if (ipt[3] == 0)
                        linkf(ipt[1], ipt[2]);
                    else
                        linke(ipt[1], ipt[2]);
                    break;
                default:
                    break;
                }
            }
        }
    }
    #define tree 
    
    *
    **
    ***
    ||
  • 相关阅读:
    JS计算每个字符出现的次数
    FCL研究-目录
    FCL研究-LINQ-System.Linq Enumerable
    FCL研究-集合- System.Collections 接口和对象集合
    Vimperator常用快捷键
    【转】WCF光芒下的Web Service
    【转】GridView 加载空行并点击编辑每一个单元格
    [转]在C#程序设计中使用Win32类库
    OpenOffice实现Office转Pdf(支持自定义添加水印、页眉、页脚)
    VUE 动态路由
  • 原文地址:https://www.cnblogs.com/tobyw/p/9460501.html
Copyright © 2011-2022 走看看