2019 CCPC wannfly winter camp Day 8

Souls-like Game

直接线段树合并矩阵会被卡T掉,因为修改的复杂度比询问的复杂度多一个log,所以我们考虑优化修改。

修改的瓶颈在于打lazy的时候, 所以我们预处理出每个修改矩阵2的幂次,然后直接更新。

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 998244353
#define ld long double
//#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
//#define base 1000000000000000000
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const ull ba=233;
const db eps=1e-9;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N = 200000+10,maxn=4000000+10,inf=0x3f3f3f3f;

int nn, tot;

struct Matrix {
    int a[3][3];
    Matrix() {
        memset(a, 0, sizeof(a));
    }
    void read() {
        for(int i=0;i<3;i++)for(int j=0;j<3;j++)scanf("%d",&a[i][j]);
    }
    void pr()
    {
        for(int i=0;i<3;i++) {
            for(int j=0;j<3;j++)printf("%d ",a[i][j]);
            puts("");
        }
    }
    void init() {
        for(int i = 0; i < 3; i++)
            a[i][i] = 1;
    }
    Matrix operator * (const Matrix &B) const {
        Matrix C;
        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
                for(int k = 0; k < 3; k++)
                    C.a[i][j] = (C.a[i][j] + 1ll * a[i][k] * B.a[k][j]) % mod;
        return C;
    }
    Matrix operator ^ (int b) {
        Matrix C; C.init();
        Matrix A = (*this);
        while(b) {
            if(b & 1) C = C * A;
            A = A * A; b >>= 1;
        }
        return C;
    }
} o[N<<2], tmp[N][20];
int lazy[N<<2], depth[N<<2], cnt;
bool ok[N<<2];

void pushup(int rt){o[rt]=o[rt<<1]*o[rt<<1|1];}
void pushdown(int l,int r,int rt)
{
    if(!ok[rt]) return;
    int m=(l+r)>>1;
    o[rt<<1]=tmp[lazy[rt]][depth[rt<<1]];
    o[rt<<1|1]=tmp[lazy[rt]][depth[rt<<1|1]];
    lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
    ok[rt<<1] = ok[rt<<1|1] = true;
    ok[rt] = false;
}

void build(int l,int r,int rt,int deep)
{   depth[rt] = deep;
    ok[rt] = false;
    if(l==r){if(l <= nn) o[rt].read();return;}
    int m=(l+r)>>1;
    build(ls, deep-1);build(rs, deep-1);
    pushup(rt);
}

void update(int L,int R,int who,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        o[rt] = tmp[who][depth[rt]];
        lazy[rt] = who;
        ok[rt] = true;
        return;
    }
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,who,ls);
    if(m<R)update(L,R,who,rs);
    pushup(rt);
}
Matrix query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) {
        return o[rt];
    }
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    Matrix te;te.init();
    if(L<=m)te=te*query(L,R,ls);
    if(m<R)te=te*query(L,R,rs);
    return te;
}

int main() {
    int n, m, p;
    scanf("%d%d",&n,&m);n--;
    nn = n;
    for(p = 0; (1 << p) < n; p++);
    n = 1 << p;
    build(1, n, 1, p);
    while(m--)
    {
        int op,l,r;scanf("%d%d%d",&op,&l,&r);
        if(op==1) {
            cnt++;
            tmp[cnt][0].read();
            for(int i = 1; i < 20; i++)
                tmp[cnt][i] = tmp[cnt][i - 1] * tmp[cnt][i - 1];
            update(l,r,cnt,1,n,1);
        } else {
            --r;
            Matrix te=query(l,r,1,n,1);
            ll ans=0;
            for(int i=0;i<3;i++)for(int j=0;j<3;j++)add(ans,1ll*te.a[i][j]);
            printf("%lld\n",ans);
        }
    }
    return 0;
}
/*
*/
View Code

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/10333344.html