1. 程式人生 > >[Codeforces 920F] SUM and REPLACE

[Codeforces 920F] SUM and REPLACE

[題目連結]

         https://codeforces.com/contest/920/problem/F

[演算法]

        顯然 , 一個10 ^ 6以內的數在經過最多6次操作後就會變為1或2 , 這是因為一個數的因子個數是根號級別的

        用篩法預處理10 ^ 6以內每個數的因數個數 , 用線段樹維護即可 , 修改時可以暴力地修改到葉子節點

        時間複雜度 : O(NlogN)

[程式碼]

        

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 10;
const int MAXP = 1e6 + 10;
typedef long long ll;
typedef long double ld;

int n , m;
int val[MAXN] , p[MAXP];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template 
<typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1
) + c - '0'; x *= f; } struct Segment_Tree { struct Node { int l ,r; ll cnt; bool flg; } a[MAXN << 2]; inline void build(int index , int l , int r) { a[index].l = l , a[index].r = r; if (l == r) { a[index].cnt = val[l]; a[index].flg = (a[index].cnt == 1 || a[index].cnt == 2); return; } int mid = (l + r) >> 1; build(index << 1 , l , mid); build(index << 1 | 1 , mid + 1 , r); update(index); } inline bool update(int index) { a[index].flg = a[index << 1].flg & a[index << 1 | 1].flg; a[index].cnt = a[index << 1].cnt + a[index << 1 | 1].cnt; } inline void modify(int index , int l , int r) { int mid =(a[index].l + a[index].r) >> 1; if (a[index].flg) return; if (a[index].l == l && a[index].r == r) { if (l == r) { a[index].cnt = p[a[index].cnt]; a[index].flg = (a[index].cnt == 1 || a[index].cnt == 2); return; } else { modify(index << 1 , l , mid); modify(index << 1 | 1 , mid + 1 , r); update(index); } return; } if (mid >= r) modify(index << 1 , l , r); else if (mid + 1 <= l) modify(index << 1 | 1 , l , r); else { modify(index << 1 , l , mid); modify(index << 1 | 1 , mid + 1 , r); } update(index); } inline ll query(int index , int l , int r) { if (a[index].l == l && a[index].r == r) return a[index].cnt; else { int mid = (a[index].l + a[index].r) >> 1; if (mid >= r) return query(index << 1 , l , r); else if (mid + 1 <= l) return query(index << 1 | 1 , l , r); else return query(index << 1 , l , mid) + query(index << 1 | 1 , mid + 1 , r); } } } SGT; int main() { read(n); read(m); for (int i = 1; i < MAXP; i++) { for (int j = i; j < MAXP; j += i) ++p[j]; } for (int i = 1; i <= n; i++) read(val[i]); SGT.build(1 , 1 , n); for (int i = 1; i <= m; i++) { int type; read(type); if (type == 1) { int l , r; read(l); read(r); SGT.modify(1 , l , r); } else { int l , r; read(l); read(r); printf("%lld\n" , SGT.query(1 , l , r)); } } return 0; }