题解 CF438D 【The Child and Sequence】

Juan_feng

2018-11-26 20:04:19

Solution

## 分块也可以通过此题qwq ~~跑的贼慢= =~~ 咳咳,进入正题。 区间求和和单点修改都是基操,这里就不深入讲解了 看看区间取% 方法之前的dalao都说了,维护每一个块内的最大值,如果这个最大值小于膜数就直接跳过此块,散块暴力修改,因为每次修改至少让一个数减小一半,所以每个数最多修改次数为log级别的。 **然而分块怎么维护最大值呢= =?** 愚蠢如我自然只能用蠢办法了QAQ : 用vector保存每个块内的数值大小, 修改的时候只要erase掉当前数值再insert修改后的数值就好了。 取最大值的时候就直接取出vector的最后一个值。 大概就是这样啊qaq **感觉还有优化的空间**,小蒟蒻的题解权当抛砖引玉了qwqwq 如果还有什么问题或者意见建议的话不妨直接私信小蒟蒻qaq **那么代码如下** ``` #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> #define maxn 100010 #define ll long long #define re register #define FOR(i, l, r) for(re ll i = l; i <= r; ++i) using namespace std; ll n, m, c, r, t, x, y, z, k; //小蒟蒻太懒就全开上long long了 ll sq; ll a[maxn], b[maxn], maxx[maxn], ans[maxn]; vector<ll> ve[1001]; inline void in(re ll &x){ //快读 x=0;ll f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c==-1) return; if(c=='-')f=-1; c=getchar(); } while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+(c^'0'); c=getchar(); } x=x*f; } void out(re ll a){ if(a<0){ a*=-1; putchar('-'); } if(a>=10)out(a/10); putchar(a%10+'0'); } ll query(ll x, ll y) { //求和 ll anss = 0; FOR(i, x, min(y, b[x]*sq)) anss += a[i]; if(b[x] != b[y]) FOR(i, (b[y]-1)*sq+1, y) anss += a[i]; FOR(i, b[x]+1, b[y]-1) anss += ans[i]; return anss; } void change(ll x, ll y, ll p) { //区间取% FOR(i, x, min(y, b[x]*sq)) { //散块暴力修改 if(a[i] >= p) { ans[b[x]] -= a[i]; ve[b[x]].erase(lower_bound(ve[b[x]].begin(), ve[b[x]].end(), a[i])); a[i] %= p; ans[b[x]] += a[i]; ve[b[x]].insert(lower_bound(ve[b[x]].begin(), ve[b[x]].end(), a[i]), a[i]); } } if(b[x] != b[y]) FOR(i, (b[y]-1)*sq+1, y) { if(a[i] >= p) { ans[b[y]] -= a[i]; ve[b[y]].erase(lower_bound(ve[b[y]].begin(), ve[b[y]].end(), a[i])); a[i] %= p; ans[b[y]] += a[i]; ve[b[y]].insert(lower_bound(ve[b[y]].begin(), ve[b[y]].end(), a[i]), a[i]); } } FOR(i, b[x]+1, b[y]-1) { //整块判断是否需要修改,是则暴力去找 ll nc = ve[i].size(); if(ve[i][nc-1] >= p) FOR(j, (i-1)*sq+1, i*sq) { if(a[j] >= p) { ans[i] -= a[j]; ve[i].erase(lower_bound(ve[i].begin(), ve[i].end(), a[j])); a[j] %= p; ans[i] += a[j]; ve[i].insert(lower_bound(ve[i].begin(), ve[i].end(), a[j]), a[j]); } } } } int main() { in(n), in(m); sq = sqrt(n); FOR(i, 1, n) { //预处理 in(a[i]), b[i] = (i-1)/sq+1, ans[b[i]] += a[i]; ve[b[i]].insert(lower_bound(ve[b[i]].begin(), ve[b[i]].end(), a[i]), a[i]); } FOR(i, 1, m) { in(t); if(t == 1) { in(x), in(y); out(query(x, y)); putchar(10); } if(t == 2) { in(x), in(y), in(z); change(x, y, z); } if(t == 3) { in(x), in(k); ans[b[x]] -= a[x]; ve[b[x]].erase(lower_bound(ve[b[x]].begin(), ve[b[x]].end(), a[x])); a[x] = k; ans[b[x]] += k; ve[b[x]].insert(lower_bound(ve[b[x]].begin(), ve[b[x]].end(), a[x]), a[x]); } } return 0; // 功德圆满 } ```