洛谷P3987 我永远喜欢珂朵莉~(set 树状数组)

题意

题目链接

Sol

不会卡常,自愧不如。下面的代码只有66分。我实在懒得手写平衡树了。。

思路比较直观:拿个set维护每个数出现的位置,再写个线段树维护区间和

#include<bits/stdc++.h>
#define LL long long 
const int MAXN = 5e5 + 10, INF = 1e9 + 7;
using namespace std;
template<typename A, typename B> inline bool chmax(A &x, B y) {
    if(y > x) {x = y; return 1;}
    else return 0;
}
template<typename A, typename B> inline bool chmin(A &x, B y) {
    if(y < x) {x = y; return 1;}
    else return 0;
}
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M, op[MAXN], ql[MAXN], qr[MAXN], val[MAXN];
LL a[MAXN];
bool ha[MAXN];
set<int> s[MAXN];
void gao(int pos,  int x) {
    for(int i = 1; i * i <= x; i++) {
        if(x % i == 0) {
            if(ha[i]) s[i].insert(pos);
            if(i != (x / i))
                if(ha[x / i]) s[x / i].insert(pos);
        }
    }
}
#define lb(x) (x & (-x))
LL T[MAXN];
void Add(int p, int v) {
    while(p <= N) T[p] += v, p += lb(p);
}
LL Sum(int x) {
    LL ans = 0;
    while(x) ans += T[x], x -= lb(x);
    return ans;
}
LL Query(int l, int r) {
    return Sum(r) - Sum(l - 1);
}
void Modify(int p, int v) {
    Add(p, -a[p]);
    Add(p, a[p] / v);
}

void Change(int l, int r, int x) {
    auto it = s[x].lower_bound(l);
    while(1) {
        int pos = *it;
        if(it == s[x].end() || pos > r) return ;
        if(a[pos] % x != 0) {it++; s[x].erase(prev(it)); continue;}
        else Modify(pos, x), a[pos] /= x;
        it++;
    }
}
int main() {
//	freopen("a.in", "r", stdin);
    N = read(); M = read();
    for(int i = 1; i <= N; i++) a[i] = read(), Add(i, a[i]);
    for(int i = 1; i <= M; i++) {
        op[i] = read(), ql[i] = read(); qr[i] = read();
        if(op[i] == 1) val[i] = read(), ha[val[i]] = 1;
    }
    for(int i = 1; i <= N; i++) gao(i, a[i]);
    for(int i = 1; i <= M; i++) {
        if(op[i] == 1) {
            if(val[i] != 1) Change(ql[i], qr[i], val[i]);
        } else cout << Query(ql[i], qr[i]) << '\n';
    }
    return 0;
}
posted @ 2019-02-09 16:44  自为风月马前卒  阅读(446)  评论(0编辑  收藏  举报

Contact with me