(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

Catalog

@

Problem:传送门

 Portal

 原题目描述在最下面。

 简单的说,每个点是一个矩阵,区间赋值和区间求积。

Solution:

\(div2\)版本就\(O(n*m*9)\)暴力更新暴力矩阵乘法求答案就行了,代码挺短的,有需要的话去另一篇博客里有代码。



\(div1\)题解就上面这个,相信大家看完应该都能\(ac\)。

本题只有两种操作,区间赋值和区间求和(矩阵的积)。很自然就想到要用线段树优化咯,然后线段树每个节点都是一个矩阵。

但是这题要先把区间长度扩展为2的幂次,为什么呢?因为:

长度为\(n\)的区间长度有大概\(log(n)\)种,但是当\(n\)不是\(2\)的幂次的时候,各种区间的长度是没有规律的。

这题线段树每个节点维护的是矩阵信息,用\(lazy\)标记优化区间赋值时,其实就是求矩阵的\(k\)次幂。

因为会有很多区间的长度相同,可以先把矩阵的k次幂预处理出来。

而只有当总长度是2的幂次时,每个节点覆盖的区间长度都会是2的幂次。这样就解释完了。

理解了这个,这题就随便写了。

AC_Code:

//哇,这题ac完感觉好爽啊
//第一次写这种结构体线段树还重载操作符的,海星
//没有人写博客,只能看着官方题解意会解法
#include<bits/stdc++.h>
#define clr(a, b) memset(a,b,sizeof((a)))
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long LL; const int MXN = 2e5 + 7;
const LL mod = 998244353; int n, m, Q;
int ar[MXN][3][3], two[33];
int lazy[MXN<<2][3][3], flag[MXN<<2];
map<int, int> mp; struct edge {
int opt, l, r;
int ar[3][3];
}node[MXN];
struct lp {
int sum[3][3];
friend lp operator *(const lp&a, const lp&b) {
lp c;
clr(c.sum, 0);
for(int k = 0; k < 3; ++k) for(int i = 0; i < 3; ++i) for(int j = 0; j < 3; ++j) {
c.sum[i][j] = (c.sum[i][j]+(LL)a.sum[i][k]*b.sum[k][j])%mod;
}
return c;
}
}cw[MXN<<2], tp[MXN][33]; void push_up(int rt) {
cw[rt] = cw[lson] * cw[rson];
}
void build(int l,int r,int rt) {
flag[rt] = -1;
if(l == r) {
for(int i = 0; i < 3; ++i) for(int j = 0; j < 3; ++j) cw[rt].sum[i][j] = ar[l][i][j];
return ;
}
int mid = (l + r) >> 1;
build(l, mid, lson); build(mid+1,r,rson);
push_up(rt);
}
void push_down(int l,int mid,int r,int rt) {
if(flag[rt] == -1) return;
flag[lson] = flag[rson] = flag[rt];
for(int i = 0; i < 3; ++i) for(int j = 0; j < 3; ++j) lazy[lson][i][j] = lazy[rt][i][j], lazy[rson][i][j] = lazy[rt][i][j];
cw[lson] = tp[flag[rt]][mp[mid-l+1]-1];
cw[rson] = tp[flag[rt]][mp[r-mid]-1];
assert(mp[mid-l+1]); assert(mp[r-mid]);
flag[rt] = -1;
}
void update(int L,int R,int id,int l,int r,int rt) {
if(L <= l && r <= R) {
flag[rt] = id;
for(int i = 0; i < 3; ++i) for(int j = 0; j < 3; ++j) lazy[rt][i][j] = node[id].ar[i][j];
assert(mp[r-l+1]);
cw[rt] = tp[id][mp[r-l+1]-1];
return ;
}
int mid = (l + r) >> 1;
push_down(l, mid, r, rt);
if(L > mid) update(L, R, id, mid+1, r, rson);
else if(R <= mid) update(L, R, id, l, mid, lson);
else {
update(L,mid,id,l,mid,lson); update(mid+1,R,id,mid+1,r,rson);
}
push_up(rt);
}
lp query(int L,int R,int l,int r,int rt) {
if(L <= l && r <= R) {
return cw[rt];
}
int mid = (l + r) >> 1;
push_down(l, mid, r, rt);
if(L > mid) return query(L, R, mid+1, r, rson);
else if(R <= mid) return query(L, R, l, mid, lson);
else {
return query(L,mid,l,mid,lson)*query(mid+1,R,mid+1,r,rson);
}
}
int main() {
two[0] = 1, mp[1] = 1;
for(int i = 1; i <= 17; ++i) two[i] = two[i-1] << 1, mp[1<<i] = i + 1;
scanf("%d%d", &n, &Q);
for(int i = 1; i < n; ++i) {
for(int j = 0; j < 3; ++j) for(int k = 0; k < 3; ++k) scanf("%d", &ar[i][j][k]);
}
m = 2;
while(m < n) m <<= 1;
build(1, m, 1);
int opt, l, r;
for(int i = 1; i <= Q; ++i) {
scanf("%d%d%d", &node[i].opt, &node[i].l, &node[i].r);
if(node[i].opt == 1) {
for(int k = 0; k < 3; ++k) for(int j = 0; j < 3; ++j) {
scanf("%d", &node[i].ar[k][j]);
tp[i][0].sum[k][j] = node[i].ar[k][j];
}
for(int k = 1; k <= 17; ++k) {
tp[i][k] = tp[i][k-1] * tp[i][k-1];
}
update(node[i].l, node[i].r, i, 1, m, 1);
}else {
LL ans = 0;
lp a = query(node[i].l, node[i].r-1, 1, m, 1);
for(int i = 0; i < 3; ++i) for(int j = 0; j < 3; ++j) ans = (ans + a.sum[i][j]) % mod;
printf("%lld\n", ans);
}
}
return 0;
}

Problem Description:

Wannafly Winter Camp Day8(Div1,onsite) E题 Souls-like Game 线段树 矩阵乘法的更多相关文章

  1. CCPC-Wannafly Winter Camp Day8 (Div2, onsite) A 题 Aqours (精巧的树形DP)

    题目链接: https://www.cometoj.com/contest/29/problem/A?problem_id=414 Aqours 题目描述 Aqours 正在 LoveLive! 决赛 ...

  2. CCPC-Wannafly Winter Camp Day8 (Div2, onsite) 补题

    A Aqours 题解: https://www.cnblogs.com/qieqiemin/p/11251645.html D:吉良吉影的奇妙计划 (暴力打表) 题目描述 吉良吉影是一个平凡的上班族 ...

  3. Wannafly Winter Camp 2020 Day 5C Self-Adjusting Segment Tree - 区间dp,线段树

    给定 \(m\) 个询问,每个询问是一个区间 \([l,r]\),你需要通过自由地设定每个节点的 \(mid\),设计一种"自适应线段树",使得在这个线段树上跑这 \(m\) 个区 ...

  4. Wannafly Winter Camp Day5 Div1 E题 Fast Kronecker Transform 转化为NTT或FFT

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog @ Problem:传送门  原题目描述在最下面.  对给定的式子算解.   ...

  5. CCPC-Wannafly Winter Camp Day8 (Div2, onsite)

    咕咕咕.    camp补题. 传送门:https://www.zhixincode.com/contest/29/problems A.Aqours 题意:有一棵有根树,根节点为1,给出每个结点的父 ...

  6. MAZE(2019年牛客多校第二场E题+线段树+矩阵乘法)

    题目链接 传送门 题意 在一张\(n\times m\)的矩阵里面,你每次可以往左右和下三个方向移动(不能回到上一次所在的格子),\(1\)表示这个位置是墙,\(0\)为空地. 现在有\(q\)次操作 ...

  7. 2019 wannafly winter camp day5-8代码库

    目录 day5 5H div2 Nested Tree (树形dp) 5F div2 Kropki (状压dp) 5J div1 Special Judge (计算几何) 5I div1 Sortin ...

  8. Wannafly Winter Camp 2019.Day 8 div1 E.Souls-like Game(线段树 矩阵快速幂)

    题目链接 \(998244353\)写成\(99824435\)然后调这个线段树模板1.5h= = 以后要注意常量啊啊啊 \(Description\) 每个位置有一个\(3\times3\)的矩阵, ...

  9. 2019 wannafly winter camp

    2019 wannafly winter camp Name Rank Solved A B C D E F G H I J K day1 9 5/11 O O O O O day2 5 3/11 O ...

随机推荐

  1. div绝对居中、宽高自适应、多栏宽度自适应

    <style> body { background-color: #e1ddd9; font-size: 12px; font-family: Verdana, Arial, Helvet ...

  2. Django框架(二十九)—— 跨域问题

    目录 跨域问题 一.同源策略 二.CORS(跨域资源共享) 三.CORS两种请求(简单请求与非简单请求) 1.简单请求(一次请求) 2.非简单请求(两次请求) 四.CORS在Django中的应用 1. ...

  3. kafka的简介

    1. kafka是一个分布式消息队列.具有高性能.持久化.多副本备份.横向扩展能力.生产者往队列里写消息,消费者从队列里取消息进行业务逻辑.一般在架构设计中起到解耦.削峰.异步处理的作用. 1.1 b ...

  4. java中的三大特性

    java的三大特性是封装.继承.多态: 继承是OOD(面向对象设计)为了更好的建模,编程的时候是OOP(面向对象编程)提高代码的复用性.这里有个注意点:一个类只有一个直接的父类,但不是只有一个父类. ...

  5. Centos7.6安装教程 && history设置显示执行命令的时间

    一.规划磁盘使用空间(磁盘总大小200GB) /dev/sda1 mount /boot 1G mount point /dev/sda2 mount / 100G /dev/sda3 mount / ...

  6. v-distpicker 一个好用的三级联动的插件

    // 引入插件npm install v-distpicker --save import VDistpicker from 'v-distpicker' Vue.component('v-distp ...

  7. MySQL字符集不一致导致查询SQL性能问题

    今天做了一个MySQL数据库中的SQL优化. 结论是关联字段字符集不同,导致索引不可用. 查询的SQL如下: select `Alias`.`Grade`, `Alias`.`id`, `Alias` ...

  8. Linux中目录结构以及VI编辑器常见的命令操作

    1.每个目录的详细介绍,先放一张目录的整体结构在这里 /bin:是Binary的缩写,用于存放经常使用的命令 /sbin:s代表Super User,用于存放系统管理员使用的命令 /home:存放普通 ...

  9. xfce4之whisker不显示自定义启动器的解决

    对某些启动比较麻烦的程序,想创建个启动器显示在whisker里,这样就能快速启动了. 通常自己创建的desktop文件可以放~/.local/share/applications里,但是按下面这个创建 ...

  10. RemoTing 搭建简单实现

    今天对C# Remoting进行了初步的学习,废话不说... RemotingModel: Talker.cs using System;using System.Collections.Generi ...