zoukankan      html  css  js  c++  java
  • bzoj2518: [Shoi2010]滚动的正四面体

    Description

    正四面体总共有4个面,每个面都是一个正三角形。现在把它的一个面标记上字母A,如图 3中所示,A标记在底面上:

    于是,这个正四面体的滚动过程就可以用一个只包含“L”“R”“B”的字符串来描述。初始时,正四面体的A面朝下,现在SECSA将给这个正四面体一串滚动指令——当然就是一个这样的字符串——让这个正四面体每秒滚动一下。也就是说,第1秒内正四面体A面朝下,第1秒末执行第一条指令,第2秒末执行第2条指令,依次类推,直至将整个指令串执行完毕。

    你的任务就是当SECSA询问你的时候告诉他:这个正四面体在第L秒到第R秒内A面有多少秒朝着地面。当然,SECSA可能因为对这个正四面体的滚动路径不满意,他随时会修改他的某一条指令。因此你的程序应该能执行下面两个操作:

    (1)                接受SECSA修个第i条指令的信息

    (2)                回答SECSA的“在第L秒到第R秒内A面有多少秒朝着地面”的询问

    例如,假如原指令串为“LLLLB”,那么第1、4、6秒内A面是朝下的。此时,如果SECSA向你询问第3秒到第6秒的情况,你就应该回答“2”。而SECSA将第3条指令修改为“R”的话,指令串就变成了“LLRLB”,那么正四面体就只有在第1、5秒内A面朝下了。如图 5所示:

    一个正四面体的一次滚动显然有3个方向可以选择:向左(L)、向右(R)、向后(B)。如图 4所示:

    Input

    输入文件的第一行是一个整数n,表示指令串中包含的指令条数。

    输入文件的第二行是一个字符串,共包含n个字符,每个字符是“L”“R”“B”之一,表示初始的指令串。

    输入文件的第三行是一个整数m,表示你的程序需要处理的操作总数。

    接下去m行,每行描述一个操作,为以下两种格式之一:

    (1)                0 i c:表示把第i个操作改成c,c为“L”“R”“B”之一

    (2)                1 L R:表示询问第L秒到第R秒内,A面有多少秒朝下

    输入文件保证:1<=i<=N,1<=L<=R<=N+1

    Output

    输出文件对于每一个询问操作依次输出你的程序给出的回答,每个回答为一个整数,占一行。

    正四面体的A面相对于向前方向有四种位置,分别记为0,1,2,3,于是可以用线段树维护,区间维护的信息为经过区间内的指令后正四面体的状态变化,表示为一个置换,另外还要记录以状态x开始,执行区间内指令的过程中A面朝下的次数,这样就可以方便地合并区间信息了

    #include<cstdio>
    int _(){
        int x=0,c=getchar();
        while(c<48)c=getchar();
        while(c>47)x=x*10+c-48,c=getchar();
        return x;
    }
    int _id[256];
    int _c(){
        int c=getchar();
        while(c<'A'||c>'Z')c=getchar();
        return _id[c];
    }
    int nx[137777][4],c[137777][4],ss[32],sp=0;
    int nx0[3][4]={{1,2,0,3},{1,3,2,0},{1,0,3,2}};
    inline void set(int w,int x){
        for(int j=0;j<4;++j)c[w][j]=!(nx[w][j]=nx0[x][j]);
    }
    inline void up(int w){
        int l=w<<1,r=l^1;
        for(int j=0;j<4;++j)nx[w][j]=nx[r][nx[l][j]],c[w][j]=c[l][j]+c[r][nx[l][j]];
    }
    int main(){
        _id['L']=0;
        _id['R']=1;
        _id['B']=2;
        int n=_();
        for(int i=1,x,w;i<=n;++i){
            x=_c();
            set(i+65535,x);
        }
        for(int i=65535;i;--i)up(i);
        for(int q=_();q;--q)if(_()){
            int l=_()-2,r=_()-1,v=0,s=0;
            if(l>=0){
                for(int w=l+65536;w;w>>=1)if(w&1)ss[sp++]=w^1;
                while(sp){
                    int w=ss[--sp];
                    s-=c[w][v];
                    v=nx[w][v];
                }
            }else ++s;
            for(int w=r+65536;w;w>>=1)if(w&1)ss[sp++]=w^1;
            while(sp){
                int w=ss[--sp];
                s+=c[w][v];
                v=nx[w][v];
            }
            printf("%d
    ",s);
        }else{
            int w=_()+65535,x=_c();
            set(w,x);
            for(w>>=1;w;w>>=1)up(w);
        }
        return 0;
    }
  • 相关阅读:
    由js apply与call方法想到的js数据类型(原始类型和引用类型)
    ajax跨域
    悟透JavaScript(理解JS面向对象的好文章)
    Item 18: Understand the Difference between Function, Method, and Constructor Calls
    torch:hardsigmoid
    torch:CrossEntropy是个构造器,所以loss = torch.nn.CrossEntropyLoss()(output, target)这么写就对了
    检查运行文件名称与模块名称是否重复。如果重复,需要将文件名称重新命名。
    a = np.r_[1:4,0,4] 这语法有点神奇
    lstm官方demo,有好几种输出的shape
    np.c_ 这个玩意儿不是个方法,而是返回一个类然后直接和后面的ndarry相乘。。。相当于concatenate(【】,dim)
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6212228.html
Copyright © 2011-2022 走看看