zoukankan      html  css  js  c++  java
  • 计数

    给定一个长度为 N 的 0,1 数字串,加下来有 Q 个操作。
    有两类操作:
    1.输入[l,r]将区间内的数字取反。
    2.询问[l,r]内的有几中不同的子序列。

    N,Q小于1e5

    https://www.cnblogs.com/iRedBean/p/7398272.html这篇博客讲的很好。

    这道题就是把dp方程化成矩阵运算,然后线段树维护矩阵乘即可。

    hdu上卡时间,注意优化常数。。

      1 #include <cstdio>
      2 #include <cstring>
      3 using namespace std;
      4 //#define debug
      5 
      6 typedef long long LL;
      7 #ifdef debug
      8 const LL maxn=10, prime=1e9+7;
      9 #else
     10 const LL maxn=1e5+10, prime=1e9+7;
     11 #endif
     12 const LL mat1[3][3]={{1,0,0},{1,1,0},{1,0,1}};
     13 const LL mat2[3][3]={{1,1,0},{0,1,0},{0,1,1}};
     14 //前面res只开了maxn。。调了好久
     15 LL t, res[maxn*4];
     16 LL n, q, x, L, R;
     17 char s[maxn];
     18 
     19 void swap(LL &a, LL &b){
     20     LL t=a; a=b; b=t;
     21 }
     22 
     23 struct Matrix33{
     24     LL mat[3][3];
     25     //引用避免多个临时变量
     26     //这里不能写成&b,不然右值传不进来!
     27     Matrix33 operator *(Matrix33 b){
     28         Matrix33 m;
     29         for (LL i=0; i<3; ++i) for (LL j=0; j<3; ++j){
     30             m.mat[i][j]=0;
     31             for (LL k=0; k<3; ++k)
     32                 m.mat[i][j]=(m.mat[i][j]+mat[i][k]*b.mat[k][j])%prime;
     33         }
     34         return m;
     35     }
     36     void reserve(){
     37         //能加速
     38         swap(mat[0][0], mat[1][1]); swap(mat[0][1], mat[1][0]);
     39         swap(mat[0][2], mat[1][2]); swap(mat[2][0], mat[2][1]);
     40     }
     41 }seg[maxn*4], unit, ans, dp;
     42 
     43 void build(LL now, LL l, LL r){
     44     //这个必须写在前面!
     45     res[now]=0;
     46     if (l==r){
     47         memcpy(seg[now].mat, s[l-1]=='0'?mat1:mat2, sizeof(mat1));
     48         return;
     49     }
     50     LL mid=(l+r)>>1;
     51     build(now<<1, l, mid); build(now<<1|1, mid+1, r);
     52     seg[now]=seg[now<<1]*seg[now<<1|1];
     53 }
     54 
     55 void pushdown(LL now){
     56     if (res[now]){
     57         res[now<<1]^=1, res[now<<1|1]^=1;
     58         seg[now<<1].reserve();
     59         seg[now<<1|1].reserve();
     60         //忘记清零了!
     61         res[now]=0;
     62     }
     63 }
     64 
     65 void modify(LL now, LL l, LL r){
     66     if (l>=L&&r<=R){
     67         seg[now].reserve();
     68         res[now]^=1;
     69         return;
     70     }
     71     pushdown(now);
     72     LL mid=(l+r)>>1;
     73     if (mid>=L) modify(now<<1, l, mid);
     74     if (mid<R) modify(now<<1|1, mid+1, r);
     75     seg[now]=seg[now<<1]*seg[now<<1|1];
     76 }
     77 
     78 Matrix33 query(LL now, LL l, LL r){
     79     if (l>=L&&r<=R) return seg[now];
     80     pushdown(now);
     81     LL mid=(l+r)>>1;
     82     Matrix33 re=unit;
     83     if (mid>=L) re=re*query(now<<1, l, mid);
     84     if (mid<R) re=re*query(now<<1|1, mid+1, r);
     85     return re;
     86 }
     87 
     88 inline bool isdigit(char c) { return c>47&&c<58?true:false; }
     89 inline LL getuLL(){
     90     char c; LL r=0;
     91     for (c=getchar(); !isdigit(c); c=getchar());
     92     while (isdigit(c)) r=r*10+c-48, c=getchar();
     93     return r;
     94 }
     95 
     96 int main(){
     97     unit.mat[0][0]=unit.mat[1][1]=unit.mat[2][2]=1;
     98     t=getuLL();
     99     for (LL tt=0; tt<t; ++tt){
    100         n=getuLL(), q=getuLL();
    101         scanf("%s", s);
    102         build(1, 1, n);
    103         for (LL i=0; i<q; ++i){
    104             x=getuLL(), L=getuLL(), R=getuLL();
    105             if (x==1) modify(1, 1, n);
    106             if (x==2){
    107                 memset(dp.mat, 0, sizeof(dp.mat));
    108                 dp.mat[0][2]=1;
    109                 ans=query(1, 1, n); dp=dp*ans;
    110                 printf("%lld
    ", (dp.mat[0][0]%prime+dp.mat[0][1])%prime);
    111             }
    112         }
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    CSS
    171 Excel Sheet Column Number
    设计模式之组合模式
    设计模式之外观模式
    设计模式之装饰者模式
    设计模式之抽象工厂
    设计模式之工厂方法
    23种设计模式和7大原则-开篇
    设计模式之简单工厂
    每天一个Linux命令:locate(19)
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/7544805.html
Copyright © 2011-2022 走看看