题解 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:道歉,,,我时间卡的过死了,没有注意到评测机的状态

猜你喜欢

转载自www.cnblogs.com/yizimi/p/10056289.html