• hdu 5068 线段树加+dp


    这题说的是 有n 层每层 有两个门 每个门 可以到达上一层的两个门,然后求从a 层到达b 层的方案总数, 不能后退, 在同一层中不能从第一个门到达另一层

    我们只要我们可以对于每个 区间内 有dp[o][2][2] , 表示 在这个区间中 从区间起始到达区间末尾 的两个门分别设 a1,a2, b1,b2, dp[o][0][0],和dp[o][0][1],表示从从a1到b1 和 a2 到 b1 的方案总数 然后同理dp[o][1][0]dp[o][1][1],

    得到转移 通过线段树去优化他 得到转移 一旦ij 两地相通那么显然 i这个点 的 在前面这个区间的a1 a2 相应的乘上 后面 这个区间在 j 这个位置开始的方案总数, 得到他们在总区间结束时的在 b1上有多少个方案从前面区间的 a1 和a2 过来,通过这样得到整个区间的值

            for(int i=0; i<2; ++i)
                for(int j=0; j<2; ++j)
                    if(star[mid][i][j]){
                      value[o].M[0][0]=(value[o].M[0][0] + value[o*2].M[i][0] * value[o*2+1].M[0][j] % mod )%mod;
                       value[o].M[0][1]=(value[o].M[0][1] + value[o*2].M[i][1] * value[o*2+1].M[0][j]%mod )%mod;
                       value[o].M[1][0]=(value[o].M[1][0] + value[o*2].M[i][0] * value[o*2+1].M[1][j]%mod )%mod;
                       value[o].M[1][1]=(value[o].M[1][1] + value[o*2].M[i][1] * value[o*2+1].M[1][j]%mod )%mod;
    }
    #include <iostream>
    #include <cstdio>
    #include <string.h>
    using namespace std;
    typedef __int64 ll;
    const int maxn = 50005;
    const ll mod = 1000000007;
    int loc,x,y;
    struct Matx{
       ll M[2][2];
    }P;
    bool star[maxn+5][2][2];
    void maintain(int mid ,Matx &A,Matx B){
             Matx ans;
             memset(ans.M,0,sizeof(ans.M));
               for(int i=0; i<2; ++i)
                for(int j=0; j<2; ++j)
                    if(star[mid][i][j]){
                       ans.M[0][0]=(ans.M[0][0] + A.M[i][0] * B.M[0][j] )%mod;
                       ans.M[0][1]=(ans.M[0][1] + A.M[i][1] * B.M[0][j] )%mod;
                       ans.M[1][0]=(ans.M[1][0] + A.M[i][0] * B.M[1][j] )%mod;
                       ans.M[1][1]=(ans.M[1][1] + A.M[i][1] * B.M[1][j] )%mod;
                    }
              for(int i=0; i<2; ++i)
                for(int j=0; j<2; ++j)
                  A.M[i][j]=ans.M[i][j];
    }
    struct Itree{
        Matx value[maxn*4];
    
        void tain(int o,int mid){
             memset(value[o].M,0,sizeof(value[o].M));
               for(int i=0; i<2; ++i)
                for(int j=0; j<2; ++j)
                    if(star[mid][i][j]){
                      value[o].M[0][0]=(value[o].M[0][0] + value[o*2].M[i][0] * value[o*2+1].M[0][j] % mod )%mod;
                       value[o].M[0][1]=(value[o].M[0][1] + value[o*2].M[i][1] * value[o*2+1].M[0][j]%mod )%mod;
                       value[o].M[1][0]=(value[o].M[1][0] + value[o*2].M[i][0] * value[o*2+1].M[1][j]%mod )%mod;
                       value[o].M[1][1]=(value[o].M[1][1] + value[o*2].M[i][1] * value[o*2+1].M[1][j]%mod )%mod;
                    }
        }
        void build(int o, int L, int R){
             if(L==R){
               value[o].M[0][0]=1;
               value[o].M[0][1]=0;
               value[o].M[1][0]=0;
               value[o].M[1][1]=1;
                 for(int i=0; i<2; ++i)
                    for(int j=0; j<2;  ++j)
                      star[L][i][j]=true;
                 return ;
             }
             int mid= (L+R)/2;
             build( o*2 , L , mid );
             build( o*2+1 , mid+1 , R );
             tain(o,mid);
        }
    
        void update(int o, int L, int R){
                if(L==R){
                    star[L][x][y]=star[L][x][y]==false;
                    return ;
                }
                int mid=(L+R)/2;
                if(loc<=mid) update(o*2,L,mid);
                else update(o*2+1,mid+1,R);
                tain(o, mid);
        }
        void query(int o, int L, int R){
                if( (L>=x&&R<=y) ){
                    if(loc==0){
                        P=value[o];loc=1;
                    }else{
                        maintain(L-1,P,value[o]);
                    }
                    return ;
                }
                int mid = (L+R)/2;
                if(x<=mid)
                    query(o*2,L,mid);
                if(y>mid)
                    query(o*2+1,mid+1,R);
        }
    }T;
    int main()
    {
         int n,m;
         while(scanf("%d%d",&n,&m)==2){
            T.build(1,1,n);
            for(int i=0; i<m; ++i){
                 loc=0;
                 int op;
                 scanf("%d",&op);
                 if(op==0) {
                        scanf("%d%d",&x,&y);
                        T.query(1,1,n);
                        ll ans=0;
                        for(int i=0; i<2; ++i)
                             for(int j=0; j<2; ++j)
                              ans=(ans+ P.M[i][j])%mod;
                       printf("%I64d
    ",ans);
                 }else{
                     scanf("%d%d%d",&loc,&x,&y);
                     x--; y--;
                     T.update(1,1,n);
                 }
            }
         }
        return 0;
    }
    View Code
  • 相关阅读:
    setMonth 疑问
    asp.net数据格式的Format DataFormatString (备忘录)
    在日常维护中,如何实现Microsoft Lync Server 2010自动启用和同步Active Directory 域服务中所有用户帐户的信息?
    关于聊天记录的管理与查询
    DBImpExp.exe工具
    用户的批量处理
    设计模式 学习笔记(3)装饰模式、代理模式
    设计模式 学习笔记(1)简单工厂模式、策略模式
    设计模式 学习笔记(5)迪米特法则、外观模式、建造者模式
    设计模式 学习笔记(2)单一职责原则、开放封闭原则、依赖倒转原则
  • 原文地址:https://www.cnblogs.com/Opaser/p/4035120.html
Copyright © 2020-2023  润新知