• POJ 2892 Tunnel Warfare


    POJ_2892

        这个题目用splay去想还是比较直接的,但之所以感觉思路比较直接,也是因为前面又巩固、学习了一下线段树的一些对于区间合并的操作,更多的涉及线段树区间合并的题目可以参考胡浩的博客http://www.notonlysuccess.com/index.php/segment-tree-complete/

        当然,这个题目是可以用线段树去做的,而且和splay去做是比较相似的,查询的时候都是去找这个点左半部分区间的右边有多少个连续的1,以及这个点右半部分区间的左边有多少个连续的1。

        下面还是说一下我用splay做的时候的一些思路吧。

        首先要明确的就是splay上一个节点表示的是一个区间,而区间的范围就是以这个节点为根的整棵子树。我们可以用lc[](left contiguous)表示一个区间从左边开始连续有多少个1(1表是点没有被破坏),rc[](right contiguous)表示一个区间从右边开始连续有多少个1,flag[]表示当前的点是否被破坏。

        如果要查询一个点左右一共有多少个连续1,那么就只需要把这个点旋转到根,然后看这个点是否被破坏,如果没有破坏就输出rc[left[T]]+lc[right[T]]+1,否则就输出0。如果要破坏一个点,就把这个点旋转到根,然后把flag[T]变为0后,并更新一个这个节点记录的信息即可。修复一个点和破坏一个点是类似的。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 50010
    int N, M, T, node, size[MAXD], d[MAXD], cnt;
    int key[MAXD], flag[MAXD], pre[MAXD], left[MAXD], right[MAXD], lc[MAXD], rc[MAXD];
    void newnode(int &cur, int k)
    {
    cur = ++ node;
    key[cur] = k;
    flag[cur] = 1;
    size[cur] = 1;
    left[cur] = right[cur] = 0;
    }
    void update(int cur)
    {
    int ls = left[cur], rs = right[cur];
    size[cur] = size[ls] + size[rs] + 1;
    lc[cur] = lc[ls], rc[cur] = rc[rs];
    if(flag[cur] != 0)
    {
    if(rc[rs] == size[rs])
    rc[cur] += rc[ls] + 1;
    if(lc[ls] == size[ls])
    lc[cur] += lc[rs] + 1;
    }
    }
    void build(int &cur, int x, int y, int p)
    {
    int mid = (x + y) / 2;
    newnode(cur, mid);
    pre[cur] = p;
    if(x == y)
    {
    lc[cur] = rc[cur] = 1;
    return ;
    }
    if(x < mid)
    build(left[cur], x, mid - 1, cur);
    if(mid < y)
    build(right[cur], mid + 1, y, cur);
    update(cur);
    }
    void leftrotate(int x)
    {
    int y = right[x], p = pre[x];
    right[x] = left[y];
    if(right[x])
    pre[right[x]] = x;
    left[y] = x;
    pre[x] = y;
    pre[y] = p;
    if(p == 0)
    T = y;
    else
    right[p] == x ? right[p] = y : left[p] = y;
    update(x);
    }
    void rightrotate(int x)
    {
    int y = left[x], p = pre[x];
    left[x] = right[y];
    if(left[x])
    pre[left[x]] = x;
    right[y] = x;
    pre[x] = y;
    pre[y] = p;
    if(p == 0)
    T = y;
    else
    right[p] == x ? right[p] = y : left[p] = y;
    update(x);
    }
    void splay(int x, int goal)
    {
    int y, z;
    for(;;)
    {
    if((y = pre[x]) == goal)
    break;
    if((z = pre[y]) == goal)
    right[y] == x ? leftrotate(y) : rightrotate(y);
    else
    {
    if(right[z] == y)
    {
    if(right[y] == x)
    leftrotate(z), leftrotate(y);
    else
    rightrotate(y), leftrotate(z);
    }
    else
    {
    if(left[y] == x)
    rightrotate(z), rightrotate(y);
    else
    leftrotate(y), rightrotate(z);
    }
    }
    }
    update(x);
    }
    void rotateto(int v, int goal)
    {
    int i;
    for(i = T;;)
    {
    if(v == key[i])
    break;
    if(v < key[i])
    i = left[i];
    else
    i = right[i];
    }
    splay(i, goal);
    }
    void init()
    {
    T = node = left[0] = right[0] = size[0] = lc[0] = rc[0] = 0;
    build(T, 1, N, 0);
    }
    void destroy(int v)
    {
    rotateto(v, 0);
    flag[T] = 0;
    update(T);
    }
    void repair(int v)
    {
    rotateto(v, 0);
    flag[T] = 1;
    update(T);
    }
    void query(int v)
    {
    rotateto(v, 0);
    if(flag[T] == 0)
    printf("0\n");
    else
    printf("%d\n", rc[left[T]] + lc[right[T]] + 1);
    }
    void solve()
    {
    int i, j, k;
    char b[5];
    cnt = 0;
    for(i = 0; i < M; i ++)
    {
    scanf("%s", b);
    if(b[0] == 'D')
    {
    scanf("%d", &k);
    d[cnt ++] = k;
    destroy(k);
    }
    else if(b[0] == 'R')
    {
    -- cnt;
    repair(d[cnt]);
    }
    else
    {
    scanf("%d", &k);
    query(k);
    }
    }
    }
    int main()
    {
    while(scanf("%d%d", &N, &M) == 2)
    {
    init();
    solve();
    }
    return 0;
    }


  • 相关阅读:
    电源符号:VCC、VDD、VEE、VSS、VBAT各表示什么意思?
    Maven项目打包成war包并启动war包运行
    Jeecg-Boot 快速开发平台(前后端分离版本)
    ATX , UATX , MATX这三个板型有什么区别,ATX大板,MATX小板,UATX是什么板子。
    IO模型之NIO代码及其实践详解
    nio原理和示例代码
    jvisualvm远程监控tomcat
    jvisualvm 远程监控tomcat
    springmvc 自定义注解
    Bootstrap3基础 pagination 分页按钮 简单示例
  • 原文地址:https://www.cnblogs.com/staginner/p/2425560.html
Copyright © 2020-2023  润新知