• [HDU6155]Subsequence Count


    题目大意:
      给定一个01序列,支持以下两种操作:
        1.区间反转;
        2.区间求不同的子序列数量。

    思路:
      首先我们考虑区间反转,这是一个经典的线段树操作。
      接下来考虑求不同的子序列数量,在已知当前区间的情况下,我们有如下$O(n)$的动态规划:|
        $f_{i,0}=f_{i-1,0}+f_{i-1,1}+1,f_{i,1}=f_{i-1,1}//第i位为0$
        $f_{i,1}=f_{i-1,0}+f_{i-1,1}+1,f_{i,0}=f_{i-1,0}//第i位为1$
      这样的动态规划显然无法直接用线段树维护,而如果不能直接用线段树维护,上面维护的区间反转也就失去了意义。
      为了使用线段树维护这种动态规划,我们需要用矩阵表示这种递推关系。
      $left(egin{array}{}f_{i+1,0}\f_{i+1,1}\1end{array} ight)=left(egin{array}{}f_{i-1,0}\f_{i-1,1}\1end{array} ight) imesleft(egin{array}{}1&0&0\1&1&0\1&0&1end{array} ight)$
      $left(egin{array}{}f_{i+1,0}\f_{i+1,1}\1end{array} ight)=left(egin{array}{}f_{i-1,0}\f_{i-1,1}\1end{array} ight) imesleft(egin{array}{}1&1&0\0&1&0\0&1&1end{array} ight)$
      这样我们就可以保存每个区间的乘积,询问时直接相乘即可。

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<algorithm>
      4 inline int getint() {
      5     char ch;
      6     while(!isdigit(ch=getchar()));
      7     int x=ch^'0';
      8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
      9     return x;
     10 }
     11 inline int getdigit() {
     12     char ch;
     13     while(!isdigit(ch=getchar()));
     14     return ch^'0';
     15 }
     16 const int N=100001,mod=1e9+7;
     17 template<int SIZE>
     18 struct Matrix {
     19     int val[SIZE][SIZE];
     20     Matrix operator * (const Matrix &another) const {
     21         Matrix ret;
     22         for(int i=0;i<SIZE;i++) {
     23             for(int j=0;j<SIZE;j++) {
     24                 ret.val[i][j]=0;
     25                 for(int k=0;k<SIZE;k++) {
     26                     ret.val[i][j]+=(long long)val[i][k]*another.val[k][j]%mod;
     27                     ret.val[i][j]%=mod;
     28                 }
     29             }
     30         }
     31         return ret;
     32     }
     33     void operator *= (const Matrix &another) {
     34         *this=*this*another;
     35     }
     36     void flip() {
     37         std::swap(val[0][0],val[1][1]);
     38         std::swap(val[0][1],val[1][0]);
     39         std::swap(val[0][2],val[1][2]);
     40         std::swap(val[2][0],val[2][1]);
     41     }
     42     int calc() {
     43         return (val[2][0]+val[2][1])%mod;
     44     }
     45 };
     46 const Matrix<3> m[2]={
     47     {1,0,0,
     48      1,1,0,
     49      1,0,1},
     50     {1,1,0,
     51      0,1,0,
     52      0,1,1}
     53 };
     54 const Matrix<3> E={
     55     1,0,0,
     56     0,1,0,
     57     0,0,1
     58 };
     59 class SegmentTree {
     60     private:
     61         #define _left <<1
     62         #define _right <<1|1
     63         Matrix<3> val[N<<2];
     64         bool tag[N<<2];
     65         void push_up(const int p) {
     66             val[p]=val[p _left]*val[p _right];
     67         }
     68         void push_down(const int p) {
     69             if(!tag[p]) return;
     70             val[p _left].flip();
     71             val[p _right].flip();
     72             tag[p _left]^=true;
     73             tag[p _right]^=true;
     74             tag[p]=false;
     75         }
     76     public:
     77         void build(const int p,const int b,const int e) {
     78             tag[p]=false;
     79             if(b==e) {
     80                 val[p]=m[getdigit()];
     81                 return;
     82             }
     83             int mid=(b+e)>>1;
     84             build(p _left,b,mid);
     85             build(p _right,mid+1,e);
     86             push_up(p);
     87         }
     88         void modify(const int p,const int b,const int e,const int l,const int r) {
     89             if(b==l&&e==r) {
     90                 val[p].flip();
     91                 tag[p]^=true;
     92                 return;
     93             }
     94             push_down(p);
     95             int mid=(b+e)>>1;
     96             if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r));
     97             if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r);
     98             push_up(p);
     99         }
    100         Matrix<3> query(const int p,const int b,const int e,const int l,const int r) {
    101             if(b==l&&e==r) {
    102                 return val[p];
    103             }
    104             push_down(p);
    105             int mid=(b+e)>>1;
    106             Matrix<3> ret=E;
    107             if(l<=mid) ret*=query(p _left,b,mid,l,std::min(mid,r));
    108             if(r>mid) ret*=query(p _right,mid+1,e,std::max(mid+1,l),r);
    109             return ret;
    110         }
    111 };
    112 SegmentTree t;
    113 int main() {
    114     for(int T=getint();T;T--) {
    115         int n=getint(),q=getint();
    116         t.build(1,1,n);
    117         while(q--) {
    118             int op=getint(),l=getint(),r=getint();
    119             switch(op) {
    120                 case 1: {
    121                     t.modify(1,1,n,l,r);
    122                     break;
    123                 }
    124                 case 2: {
    125                     printf("%d
    ",t.query(1,1,n,l,r).calc());
    126                     break;
    127                 }
    128             }
    129         }
    130     }
    131     return 0;
    132 }
  • 相关阅读:
    02-MySQL的安装和管理
    01-pymysql模块的安装
    异常处理
    USACO 2015 Feb Censoring
    玄武密码(bzoj4327)(JSOI2012)
    浅谈AC自动机
    Equation
    JOI五子棋
    浅谈Tarjan
    年轮蛋糕JOI2014Final
  • 原文地址:https://www.cnblogs.com/skylee03/p/7542616.html
Copyright © 2020-2023  润新知