zoukankan      html  css  js  c++  java
  • UVA 12657/COJ 1329 HN第九届省赛 链表模拟

    因为最近学了Splay,刚看到这个题目总共四种操作,把某个数移到另一个数的左边 或者右边 交换两个数 翻转整个序列,马上想到用Splay,因为总点数和总操作数都为10^5,如果用Splay把操作优化到logN级别,应该是可以再1sec过得。

    于是我就好心急的在那里敲Splay,敲着敲着就发现不对劲了,题目要求的把x移到y的左边或者右边 或者交换x和y的值,不是指序列的第x位和y位,而是就直接指数值为x和y的那两个数。所以Splay根本就不适用

    所以还是回到链表来,其实用链表也挺简单的,一开始我还想复杂了,每个x和y就固定对应自己的节点x,y,进行4个操作的时候,前三个,只要把节点x和节点y连起来或者交换即可,当然要处理好彼此的前缀和后继。然后最后一个翻转整个序列操作,其实就是把每个点的前缀变后继 后继变前缀即可。所以一开始不要固定前缀和后继,用个ch[2],再设置个p变量,初始设为0,这样 ch[p]代表前缀,ch[!p]代表后缀。当出现翻转操作,把p变一下,就直接实现了前变后 后变前的作用。

    还要注意添加 0点和 n+1点来预防越界操作,而且0点和n+1还可以作为整个序列的头部,因为对这两个点是不会有操作的,所以最后遍历链表的时候,看p的值选择0或者n+1点作为序列头部,至此,完美解决此题。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 100010
    using namespace std;
    int n,m,p;
    struct node
    {
        int ch[2];
    } num[N];
    void link(int a,int b)
    {
        num[b].ch[p]=a;
        num[a].ch[!p]=b;
    }
    int main()
    {
        int kase=0,x,y,d;
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            p=0;
            for (int i=0;i<=n;i++)
            {
                link(i,i+1);
            }
            for (int i=0;i<m;i++)
            {
                scanf("%d",&d);
                if (d==4)
                {
                    p^=1;
                    continue;
                }
                scanf("%d%d",&x,&y);
                if (d==1)
                {
                    if (num[y].ch[p]==x)
                        continue;
                    else
                    {
                        link(num[x].ch[p],num[x].ch[!p]);
                        int tmp=num[y].ch[p];
                        link(tmp,x);
                        link(x,y);
                    }
                }
                if (d==2)
                {
                    if (num[y].ch[!p]==x)
                        continue;
                    link(num[x].ch[p],num[x].ch[!p]);
                    int tmp=num[y].ch[!p];
                    link(y,x);
                    link(x,tmp);
                }
                if (d==3)
                {
                    if (num[x].ch[p]==y)
                    {
                        int tmp=num[x].ch[!p];
                        link(num[y].ch[p],x);
                        link(x,y);
                        link(y,tmp);
                        continue;
                    }
                    if (num[x].ch[!p]==y)
                    {
                        int tmp=num[x].ch[p];
                        link(x,num[y].ch[!p]);
                        link(y,x);
                        link(tmp,y);
                        continue;
                    }
                    int tmp1=num[y].ch[p];
                    int tmp2=num[y].ch[!p];
                    link(num[x].ch[p],y);
                    link(y,num[x].ch[!p]);
                    link(tmp1,x);
                    link(x,tmp2);
                }
            }
            int sta;
            if (p) sta=n+1;
            else sta=0;
            int cur=0;
            p^=1;
            long long ans=0;//结果可能超过int,所以用64位来表示
            for (int i=sta;;)
            {
                i=num[i].ch[p];
                cur++;
                if (cur>n) break;
                if (cur&1)
                {
                    ans+=(long long)i;
                }
            }
            printf("Case %d: %lld
    ",++kase,ans);
        }
        return 0;
    
    }
  • 相关阅读:
    java类继承总结一 父类类型与子类类型之间的转化问题(转)
    将子类对象引用赋值给超类对象 JAVA 编译时多态性
    JAVA访问控制变量、类变量、类方法
    java传递是引用的拷贝,既不是引用本身,更不是对象
    JAVA的StringBuffer类
    (文件名.JAVA)的文件名只能与该文件中的public类的名称一致
    类变量(静态变量)的值不能被构造函数改写
    程序启动的顺序以及实例变量相互赋值、传递拷贝的理解
    MySQL选择合适的字符集
    MySQL日期类型选择
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3600136.html
Copyright © 2011-2022 走看看