1. 程式人生 > >題解 T45322 【yizimi的字首積】

題解 T45322 【yizimi的字首積】

yizimi的字首積

字首積?

想的美!!!

此題卡分塊(別想混過去),st表,平衡樹,,,

時限在那裡吶 ~

222ms / 128MB

這時限線段樹能過?

可以的。

正解:裸的 線段樹

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 1000010
#define inf 2147483647
#define ll long long
#define ld long double
#define fi first
#define se second
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
//#define LOCAL
#define Debug(...) fprintf(stderr, __VA_ARGS__)
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
    while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
//This is AC head above...
int n, m, p;
struct tree{
    ll x;
};
struct SegmentTree{ 
    tree z[mn << 2];
    ll col[mn << 2];
    inline void update(int rt){
        z[rt].x = (z[rt << 1].x * z[rt << 1 | 1].x) % p;
    }
    inline tree operation(tree a,tree b){
        return (tree){(a.x * b.x) % p};
    }
    inline void color(int l,int r,int rt,ll v){
        z[rt].x += (r - l + 1) * v;
        col[rt] += v;
    }
    inline void push_col(int l,int r,int rt){
        if(col[rt]){
            int m = (l + r) >> 1;
            color(lson, col[rt]);color(rson, col[rt]);
            col[rt] = 0;
        }
    }
    inline void build(int l,int r,int rt){
        if(l==r){z[rt].x = read();return;}
        int m = (l + r) >> 1;build(lson);build(rson); update(rt);
    }
    inline void modify(int l,int r,int rt,int nowl,int nowr,ll v){
        if(nowl<=l && r<=nowr){color(bson, v); return;}
        int m = (l + r) >> 1; push_col(bson);
        if(nowl<=m) modify(lson, nowl, nowr, v);
        if(m<nowr)  modify(rson, nowl, nowr, v);
        update(rt);
    }
    inline tree query(int l,int r,int rt,int nowl,int nowr){
        if(nowl<=l && r<=nowr) return z[rt];
        int m = (l + r) >> 1; push_col(bson);
        if(nowl<=m){
            if(m<nowr) return operation(query(lson, nowl, nowr), query(rson, nowl, nowr));
            else       return query(lson, nowl, nowr);
        }else          return query(rson, nowl, nowr);
    }
} tr;
int main(){
    n = read(), m = read(), p = read();
    tr.build(root);
    go(i, 1, m, 1){
        int l = read(), r = read();
        cout << tr.query(root, l, r).x % p << "\n";
    } 
#ifdef LOCAL
    Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
    return 0;
}

為什麼不用字首積?

題目名字不是字首積嗎?

我用字首和思想不行嗎?

如果你用字首積,那如何實現一個數除以一個數再同餘?

逆元?

看清楚,30%的資料p為質數,

也就是說除了這30%,就不保證是不是質數啦!

不是質數,哪裡來的逆元?所以就根本不行的啦。

為什麼不用分塊

O(n sqrt n),,,

過不過的去1000000你明白的

為什麼不用ST表?

據大佬說st表的空間卡的厲害,會爆空間

為什麼不用平衡樹

我覺得只有dalao才會這麼無聊的用平衡樹,,,

常數啊,,,

線段樹大法好!!!

upd:道歉,,,我時間卡的過死了,沒有注意到評測機的狀態