【线段树维护矩阵】The 2021 Shanghai Collegiate Programming Contest I. 对线
2021-09-09 14:18:00 # ACM

题链

题目分析

三排士兵,四种操作:
  $1.$ 求第 $x$ 排区间 $[L,R]$ 的士兵数量;
  $2.$ 往第 $x$ 排区间 $[L,R]$ 增加 $y$ 名士兵;
  $3.$ 将第 $x$ 排与 $y$ 排区间 $[L,R]$ 同位置的士兵交换位置;
  $4.$ 第 $x$ 排的区间 $[L,R]$ 的士兵引导分身术,将分身派往第 $y$ 排对应位置;

线段树维护一个 $1 \times 3$ 的矩阵,$2$ 操作就是区间加一个 $1 \times 3$ 的矩阵, $3$ 与 $4$ 操作就是区间乘一个 $3 \times 3$ 的矩阵,$lazy$ 标记先乘后加;

如果使用 $long$ $long$,交 $c++17(64bit)$ 能省 $10s$ …;

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
#define LL long long
#define ls rt<<1
#define rs rt<<1|1
#define mod 998244353
#define MS 300009

int n,m;
struct node{
int row,col;
int cnt[3][3];
}p[MS<<2],la_mul[MS<<2],la_add[MS<<2],I,O,E;
bool la_ok[MS<<2];

void init(){
I = {3,3}; memset(I.cnt,0,sizeof I.cnt);
for(int i=0;i<3;i++) I.cnt[i][i] = 1;
O = {1,3}; memset(O.cnt,0,sizeof O.cnt);
E = {3,3}; memset(E.cnt,0,sizeof E.cnt);
}

node operator + (node t1, node t2){
for(int i=0;i<t1.row;i++)
for(int j=0;j<t1.col;j++)
t1.cnt[i][j] = (1LL*t1.cnt[i][j] + t2.cnt[i][j])%mod;
return t1;
}

node operator * (node t1, node t2){
node t; t = {t1.row,t2.col};
memset(t.cnt,0,sizeof t.cnt);
for(int i=0;i<t.row;i++)
for(int j=0;j<t.col;j++)
for(int k=0;k<t1.col;k++)
t.cnt[i][j] = (1LL*t.cnt[i][j] + 1LL*t1.cnt[i][k]*t2.cnt[k][j])%mod;
return t;
}

node operator * (node t, LL x){
for(int i=0;i<t.row;i++)
for(int j=0;j<t.col;j++)
t.cnt[i][j] = (1LL * t.cnt[i][j] * x)%mod;
return t;
}

void update_mul(int rt,node C){
p[rt] = p[rt] * C;
la_mul[rt] = la_mul[rt] * C;
la_add[rt] = la_add[rt] * C;
la_ok[rt] = 1;
}

void update_add(int rt,node C,LL len){
p[rt] = p[rt] + C*len;
la_add[rt] = la_add[rt] + C;
la_ok[rt] = 1;
}

void push_up(int rt){
p[rt] = p[ls] + p[rs];
}

void push_down(int rt,int l,int r){
if(la_ok[rt]){
int m = l+r>>1;
update_mul(ls,la_mul[rt]);
update_add(ls,la_add[rt],m-l+1);
update_mul(rs,la_mul[rt]);
update_add(rs,la_add[rt],r-m);
la_mul[rt] = I;
la_add[rt] = O;
la_ok[rt] = 0;
}
}

void build(int l,int r,int rt){
la_mul[rt] = I;
la_add[rt] = O;
p[rt] = O;
if(l == r) return;
int m = l+r>>1;
build(l,m,ls);
build(m+1,r,rs);
}

void modify_add(int L,int R,int l,int r,int rt,node C){
if(L <= l && r <= R){
update_add(rt,C,r-l+1);
return;
}
int m = l+r>>1;
push_down(rt,l,r);
if(m >= L) modify_add(L,R,l,m,ls,C);
if(m < R) modify_add(L,R,m+1,r,rs,C);
push_up(rt);
}

void modify_mul(int L,int R,int l,int r,int rt,node C){
if(L <= l && r <= R){
update_mul(rt,C);
return;
}
int m = l+r>>1;
push_down(rt,l,r);
if(m >= L) modify_mul(L,R,l,m,ls,C);
if(m < R) modify_mul(L,R,m+1,r,rs,C);
push_up(rt);
}

int query(int L,int R,int l,int r,int rt,int t){
if(L <= l && r <= R){
return p[rt].cnt[0][t];
}
int m = l+r>>1;
push_down(rt,l,r);
int ans = 0;
if(m >= L) ans = (ans + query(L,R,l,m,ls,t) )%mod;
if(m < R) ans = (ans + query(L,R,m+1,r,rs,t))%mod;
return ans%mod;
}

void solve(){
init();
cin >> n >> m;
build(1,n,1);
while(m--){
int op;
cin >> op;
if(op == 0){
int x,l,r; cin >> x >> l >> r; x--;
cout << query(l,r,1,n,1,x) << "\n";
}
else if(op == 1){
int x,l,r,y; cin >> x >> l >> r >> y; x--;
node C = O;
C.cnt[0][x] = y;
modify_add(l,r,1,n,1,C);
}
else if(op == 2){
int x,y,l,r; cin >> x >> y >> l >> r; x--; y--;
node C = I;
swap(C.cnt[x][x],C.cnt[y][x]);
swap(C.cnt[y][y],C.cnt[x][y]);
modify_mul(l,r,1,n,1,C);
}
else{
int x,y,l,r; cin >> x >> y >> l >> r; x--; y--;
node C = I;
C.cnt[x][y]++;
modify_mul(l,r,1,n,1,C);
}
}
}

int main() {
ios::sync_with_stdio(false);
int ce;
// cin >> ce;
ce = 1;
while(ce--){
solve();
}



return 0;
}
/*


*/
Prev
2021-09-09 14:18:00 # ACM
Next