貝殼找房戶外拓展(中等) 掃描線
阿新 • • 發佈:2019-02-06
線上段樹上寫了矩陣乘法,其實只是2*2的矩陣,手寫轉移似乎更好。
#include<bits/stdc++.h> using namespace std; const int mo = 323232323; const int maxn = 1e5 + 100; struct I_node{ int p, q, x, y, flog, k; bool operator < (const I_node & u)const{ if(x == u.x) return flog > u.flog; return x < u.x; } }I[maxn * 2]; struct node{ long long a[2][2]; node(long long x = 0){ for(int i = 0; i < 2; i++){ for(int j = 0; j < 2; j++){ a[i][j] = x; } } } node operator * (node u)const{ node c(0); for(int i = 0; i < 2; i++){ for(int k = 0; k < 2; k++){ if(a[i][k]) for(int j = 0; j < 2; j++){ c.a[i][j] = (c.a[i][j] + a[i][k] * u.a[k][j]) % mo; } } } return c; } }one, change; node seg[maxn << 2]; void pushup(int node){ seg[node] = seg[node << 1] * seg[node << 1 | 1]; } void build(int l, int r, int node){ if(l == r){ seg[node] = one; return ; } int mid = (l + r) >> 1; build(l, mid, node << 1); build(mid + 1, r, node << 1 | 1); pushup(node); return ; } void update(int ind, int l, int r, int node){ if(l == r){ seg[node] = change; return ; } // cout << l << " " << r << endl; int mid = (l + r) >> 1; if(ind <= mid){ update(ind, l, mid, node << 1); } else{ update(ind, mid + 1, r, node << 1 | 1); } pushup(node); return ; } node query(int le, int ri, int l, int r, int node){ if(l >= le && r <= ri){ return seg[node]; } int mid = (l + r) >> 1; if(le <= mid && ri > mid){ return query(le, ri, l, mid, node << 1) * query(le, ri, mid + 1, r, node << 1 | 1); } else if(le <= mid){ return query(le, ri, l, mid, node << 1); } else if(ri > mid){ return query(le, ri, mid + 1, r, node << 1 | 1); } } void pri(node u){ for(int i = 0; i < 2; i++){ for(int j = 0; j < 2; j++){ cout << u.a[i][j] << " "; } cout << endl; } } int book[maxn]; long long ans[maxn]; int main(){ one.a[0][1] = one.a[1][0] = 0; for(int i = 0; i < 2; i++){ one.a[i][i] = 1; } int n, m, Q, l, r, y, tp, tq, x; cin >> n >> m >> Q; char type[2]; int k = 0; int In = 0, Qn = 0; while(Q--){ scanf("%s", type); if(type[0] == 'I'){ k++; scanf("%d %d %d %d %d", &l, &r, &y, &tp, &tq); I[In].p = tp, I[In].q = tq, I[In].k = k, I[In].flog = 1, I[In].x = l, I[In].y = y; In++; I[In].p = tp, I[In].q = tq, I[In].k = k, I[In].flog = -1, I[In].x = r, I[In].y = y; In++; book[k] = 1; } else if(type[0] == 'Q'){ scanf("%d %d %d", &x, &l, &r); I[In].p = l, I[In].q = r, I[In].x = x; I[In].k = Qn++; I[In].flog = 0; In++; } else{ scanf("%d", &l); book[l] = 0; } } build(1, m, 1); sort(I, I + In); for(int i = 0; i < In; i++){ if(I[i].flog == 0){ // cout << I[i].flog << " " << I[i].x << " " << I[i].y << endl; node be(0); be.a[0][1] = 1; be = be * query(I[i].p, I[i].q, 1, m, 1); ans[I[i].k] = be.a[0][0]; } else if(I[i].flog == 1){ if(!book[I[i].k]) continue; // cout << I[i].flog << " " << I[i].x << " " << I[i].y << endl; change.a[0][0] = I[i].p; change.a[0][1] = 0; change.a[1][0] = I[i].q; change.a[1][1] = 1; update(I[i].y, 1, m, 1); } else{ if(!book[I[i].k]) continue; // cout << I[i].flog << " " << I[i].x << " " << I[i].y << endl; change = one; update(I[i].y, 1, m, 1); } } for(int i = 0; i < Qn; i++){ printf("%lld\n", ans[i]); } return 0; }