The Child and Sequence
传送门 Problem - 438D - Codeforces
At the children’s day, the child came to Picks’s house, and messed his house up. Picks was angry at him. A lot of important things were lost, in particular the favorite sequence of Picks.
Fortunately, Picks remembers how to repair the sequence. Initially he should create an integer array a[1], a[2], …, a[n]. Then he should perform a sequence of m operations. An operation can be one of the following:
- Print operation l, r. Picks should write down the value of
.
- Modulo operation l, r, x. Picks should perform assignment a[i] = a[i] mod x for each i (l ≤ i ≤ r).
- Set operation k, x. Picks should set the value of a[k] to x (in other words perform an assignment a[k] = x).
Can you help Picks to perform the whole sequence of operations?
Input
The first line of input contains two integer: n, m (1 ≤ n, m ≤ 105). The second line contains n integers, separated by space: a[1], a[2], …, a[n] (1 ≤ a[i] ≤ 109) — initial value of array elements.
Each of the next m lines begins with a number type .
- If type = 1, there will be two integers more in the line: l, r (1 ≤ l ≤ r ≤ n), which correspond the operation 1.
- If type = 2, there will be three integers more in the line: l, r, x (1 ≤ l ≤ r ≤ n; 1 ≤ x ≤ 109), which correspond the operation 2.
- If type = 3, there will be two integers more in the line: k, x (1 ≤ k ≤ n; 1 ≤ x ≤ 109), which correspond the operation 3.
Output
For each operation 1, please print a line containing the answer. Notice that the answer may exceed the 32-bit integer.
题意
给定序列,完成三项操作:求出序列和,对某一序列的元素a[i]=a[i] mod x,修改单点值。
思路
设reminder为a[i]%x,那么a[i]=k*x+reminder.当k=0时,不用做计算;当k!=0时,要做计算,对单点值修改。每次修改后a[i]变为不到原来的一半。
最重要的是减少修改和递归次数。维护区间最大值mx,方便查看此区间是否有修改的必要从而减少修改次数。
受到之前一题的影响(就是区间开根号的一道题),那一题是看区间大小是否等于区间和来判断是否有必要继续对区间开根。我这题也鲨臂的用了这一判断准则,只是改成了小于等于,结果WA。维护最大值我甚至还写了个query_maxV函数,结果TLE了,后来发现写在update里面,用就行了…还有就是modify在le<=s && t<=ri的时候老忘记更新犯错。然后写lson和rson会更方便,不容易写错。
#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const int maxn=1e5+6;
int n,m;
#define lson s,mid,p<<1
#define rson mid+1,t,p<<1|1
struct node {
ll v,c,sz,mx; // 区间总和 区间修改为某一定值的tag 区间大小 区间最大值
// 后来发现是单点修改,所以这个c没用了,下面的settag,pushdown也没用了
}se[maxn<<2];
ll a[maxn];
inline void update(int p) {
se[p].v=se[p<<1].v+se[p<<1|1].v;
se[p].mx=max(se[p<<1].mx,se[p<<1|1].mx);
}
inline void settag(int p,ll t) {
if(se[p].c) {
se[p].c=t; // 压标记
// 更新当前区间特征
se[p].v=se[p].sz*t;
}
}
inline void pushdown(int p) {
// 标记下传
settag(p<<1,se[p].c);
settag(p<<1|1,se[p].c);
// 刷新父标记
se[p].c=0;
}
void build(int s,int t,int p) {
if(s == t) {se[p]={a[s],0,t-s+1,a[s]};return ;}
int mid=(s+t)>>1;
build(lson),build(rson);
update(p);
}
void modify_mod(int le,int ri,int k,int s,int t,int p) {
// if(le<=s && t<=ri) if(query_maxV(le,ri,s,t,p)<k) return ;
if(se[p].mx<k) return ;
if(s == t) {se[p].v=se[p].mx=se[p].v%k;return ;}
int mid=(s+t)>>1;
if(le<=mid) modify_mod(le,ri,k,lson);
if(ri >mid) modify_mod(le,ri,k,rson);
update(p);
}
void modify_cha(int le,int ri,int k,int s,int t,int p) {
if(le<=s && t<=ri) {se[p].v=se[p].mx=k;return ;}
int mid=(s+t)>>1;
if(le<=mid) modify_cha(le,ri,k,lson);
if(ri >mid) modify_cha(le,ri,k,rson);
update(p);
}
ll query(int le,int ri,int s,int t,int p) {
if(le<=s && t<=ri) return se[p].v;
ll sum=0;
int mid=(s+t)>>1;
if(le<=mid) sum+=query(le,ri,lson);
if(ri >mid) sum+=query(le,ri,rson);
return sum;
}
int main(int argc, char const *argv[]) {
n=rr(),m=rr();
for(int i=1;i<=n;i++) {
a[i]=rr();
}
build(1,n,1);
while (m--) {
int op=rr();
if(op==1) {
int le=rr(),ri=rr();
std::cout << query(le,ri,1,n,1) << '\n';
}
else if(op==2) {
int le=rr(),ri=rr(),k=rr();
modify_mod(le,ri,k,1,n,1);
}
else if(op==3) {
int x=rr(),k=rr();
modify_cha(x,x,k,1,n,1);
}
}
return 0;
}