牛客多校第二场-H

H-0 and 1 in BIT

 op1-->-x-1

op2-->x+1

由线性代数知识推每次操作要乘的矩阵,线段树维护一个矩阵信息

 [op,d,1] 就是代表一个f(x)=kx+b的方程,根据线性代数知识用矩阵表示该方程 -> f(x)=op*x+d , 最后一个1只是凑矩阵用的 ,f代表该矩阵,因为刚开始就是x,所以op=1,d=0

 

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;

const int sz=3;
const int N=2e5+5;

string s;

struct mat {
  ll m[sz][sz];
  mat() { memset(m, 0, sizeof m); }
  mat operator-(const mat& T) const {
    mat res;
    for (int i = 0; i < sz; ++i)
      for (int j = 0; j < sz; ++j) {
        res.m[i][j] = (m[i][j] - T.m[i][j]);
      }
    return res;
  }
  mat operator+(const mat& T) const {
    mat res;
    for (int i = 0; i < sz; ++i)
      for (int j = 0; j < sz; ++j) {
        res.m[i][j] = (m[i][j] + T.m[i][j]);
      }
    return res;
  }
  mat operator*(const mat& T) const {
    mat res;
    int r;
    for (int i = 0; i < sz; ++i)
      for (int k = 0; k < sz; ++k) {
        r = m[i][k];
        for (int j = 0; j < sz; ++j)
          res.m[i][j] += T.m[k][j] * r ;
      }
    return res;
  }
  mat operator^(ll x) const {
    mat res, bas;
    for (int i = 0; i < sz; ++i) res.m[i][i] = 1;
    for (int i = 0; i < sz; ++i)
      for (int j = 0; j < sz; ++j) bas.m[i][j] = m[i][j];
    while (x) {
      if (x & 1) res = res * bas;
      bas = bas * bas;
      x >>= 1;
    }
    return res;
  }
}A,B,f,Tree[4*N],unit;

void build(int now,int l,int r){
    if(l==r){
        if(s[l-1]=='A')Tree[now]=A;
        else Tree[now]=B;
        return;
    }
    int mid=(l+r)>>1;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
    Tree[now]=Tree[now*2]*Tree[now*2+1];
}

mat qurey(int now,int l,int r,int x,int y){
    if(x<=l&&y>=r)return Tree[now];
    int mid=(l+r)>>1;
    mat ans=unit;
    if(x<=mid)ans=ans*qurey(now*2,l,mid,x,y);
    if(y>mid)ans=ans*qurey(now*2+1,mid+1,r,x,y);
    return ans;
}

int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int n,q;cin>>n>>q>>s;
    int last=0;
    A.m[0][0]=A.m[1][1]=A.m[2][1]=-1;
    A.m[2][2]=B.m[2][1]=1;
    f.m[0][0]=f.m[0][2]=1;
    for(int i=0;i<3;i++)B.m[i][i]=1,unit.m[i][i]=1;
    build(1,1,n);
    while(q--){
        int l,r;cin>>l>>r;
        string now;cin>>now;
        int rl=(last^l)%n+1,rr=(last^r)%n+1;
        l=min(rl,rr);r=max(rl,rr);
        mat calc=f*qurey(1,1,n,l,r);
        ll len=now.size(),t=0;
        for(int i=0;i<len;i++)t=t*2+(now[i]-'0');
        ll mod=1ll<<len;
        last=((t*calc.m[0][0]%mod+mod)%mod+calc.m[0][1]%mod+mod)%mod;
        for(int i=len-1;i>=0;i--){
            if((last>>i)&1)cout<<1;
            else cout<<0;
        }
        cout<<endl;
        if(last<0)break;
    }

    return 0;
} 

 

posted @ 2023-07-23 21:32  zhujio  阅读(14)  评论(0编辑  收藏  举报