codeforces438D The Child and Sequence

题面:codeforces438D

正解:线段树。

这题好像是$picks$出的题,然后无限弱化才上的$cf$。。

区间取模,每个数取模以后至少$/2$,所以暴力搞即可。

证明:若$p<x/2$,那么$x \ mod \ p<x/2$;若$p>x/2$,那么$ x \ mod \ p=x-p<x/2$。

维护一个区间最大值,如果$<p$那么就直接退出,否则把这个区间递归做再取模。

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define N (200010)
14 #define ls (x<<1)
15 #define rs (x<<1|1)
16 #define il inline
17 #define RG register
18 #define ll long long
19
20 using namespace std;
21
22 int mx[N<<2],a[N],n,m;
23 ll sum[N<<2];
24
25 il int gi(){
26     RG int x=0,q=1; RG char ch=getchar();
27     while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar();
28     if (ch==‘-‘) q=-1,ch=getchar();
29     while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar();
30     return q*x;
31 }
32
33 il void pushup(RG int x){
34     sum[x]=sum[ls]+sum[rs],mx[x]=max(mx[ls],mx[rs]); return;
35 }
36
37 il void build(RG int x,RG int l,RG int r){
38     if (l==r){ sum[x]=mx[x]=a[l]; return; } RG int mid=(l+r)>>1;
39     build(ls,l,mid),build(rs,mid+1,r),pushup(x); return;
40 }
41
42 il void update(RG int x,RG int l,RG int r,RG int p,RG int v){
43     if (l==r){ sum[x]=mx[x]=v; return; } RG int mid=(l+r)>>1;
44     p<=mid?update(ls,l,mid,p,v):update(rs,mid+1,r,p,v);
45     pushup(x); return;
46 }
47
48 il void updatemod(RG int x,RG int l,RG int r,RG int xl,RG int xr,RG int v){
49     if (l==r){ sum[x]%=v,mx[x]%=v; return; }
50     if (mx[x]<v) return; RG int mid=(l+r)>>1;
51     if (xr<=mid) updatemod(ls,l,mid,xl,xr,v);
52     else if (xl>mid) updatemod(rs,mid+1,r,xl,xr,v);
53     else updatemod(ls,l,mid,xl,mid,v),updatemod(rs,mid+1,r,mid+1,xr,v);
54     pushup(x); return;
55 }
56
57 il ll query(RG int x,RG int l,RG int r,RG int xl,RG int xr){
58     if (xl<=l && r<=xr) return sum[x]; RG int mid=(l+r)>>1;
59     if (xr<=mid) return query(ls,l,mid,xl,xr);
60     else if (xl>mid) return query(rs,mid+1,r,xl,xr);
61     else return query(ls,l,mid,xl,mid)+query(rs,mid+1,r,mid+1,xr);
62 }
63
64 int main(){
65 #ifndef ONLINE_JUDGE
66     freopen("438D.in","r",stdin);
67     freopen("438D.out","w",stdout);
68 #endif
69     n=gi(),m=gi();
70     for (RG int i=1;i<=n;++i) a[i]=gi(); build(1,1,n);
71     for (RG int i=1,op,l,r,x,k;i<=m;++i){
72     op=gi();
73     if (op==1) l=gi(),r=gi(),printf("%I64d\n",query(1,1,n,l,r));
74     if (op==2) l=gi(),r=gi(),x=gi(),updatemod(1,1,n,l,r,x);
75     if (op==3) k=gi(),x=gi(),update(1,1,n,k,x);
76     }
77     return 0;
78 }
时间: 2024-08-28 18:57:43

codeforces438D The Child and Sequence的相关文章

Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模

D. The Child and Sequence 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

CF(438D) The Child and Sequence(线段树)

题意:对数列有三种操作: 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

CodeForces 438D The Child and Sequence(线段树)

题目:http://codeforces.com/problemset/problem/438/D 一个数取模n%m,有两种情况. 1.m>n, n%m=n; 2.m<=n, n%m<=n/2; 所以当m>n时,取模操作可以忽略. 每个a[i]最多需要log(a[i])次取模操作变为0,因此我们可以对所有取模进行暴力更新.最多要更新n*log(a[i])次,由于单次更新复杂度为log(n),所以总复杂度为n*logn*log(a[i]). #include <bits/std

Codeforces Round #250 (Div. 1) D. The Child and Sequence (线段树)

题目链接:http://codeforces.com/problemset/problem/438/D 给你n个数,m个操作,1操作是查询l到r之间的和,2操作是将l到r之间大于等于x的数xor于x,3操作是将下标为k的数变为x. 注意成段更新的时候,遇到一个区间的最大值还小于x的话就停止更新. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5

【CodeForces 438D 】The Child and Sequence

题意 要求支持三种操作  1.区间求和  2.单点修改  3.区间取模 分析 问题主要在于区间取模 需要多维护一个区间最大值,当最大值已经小于模数的时候就不需要操作了 [先开始读错题了,写了个区间修改哎我没救了] #include<bits/stdc++.h> using namespace std; #define N 110000 #define ll long long #define lc (p<<1) #define rc (p<<1|1) #define m

CF438D The Child and Sequence

外国人的数据结构题真耿直 唯一有难度的操作就是区间取模,然而这个东西可以暴力弄一下,因为一个数$x$被取模不会超过$logn$次. 证明如下(假设$x Mod   y$): 如果$y \leq \frac{x}{2}$那么$x$取模之后会小于$\frac{x}{2}$,而如果$y > \frac{x}{2}$时,$x$取模之后一定也会小于$\frac{x}{2}$ 然后就暴力一个一个取过去就好了,还有一个算是剪枝的优化,我们可以顺便维护一下区间最大值,如果区间最大值都小于当前的模数的话,那么就直

cf250D. The Child and Sequence(线段树 均摊复杂度)

题意 题目链接 单点修改,区间mod,区间和 Sol 如果x > mod ,那么 x % mod < x / 2 证明: 即得易见平凡, 仿照上例显然, 留作习题答案略, 读者自证不难. 反之亦然同理, 推论自然成立, 略去过程Q.E.D., 由上可知证毕. 然后维护个最大值就做完了.. 复杂度不知道是一个log还是两个log,大概是两个吧(线段树一个+最多改log次.) #include<bits/stdc++.h> #define Pair pair<int, int&g

CF438D The Child and Sequence 线段树

给定数列,区间查询和,区间取模,单点修改. n,m小于10^5 ...当区间最值小于模数时,就直接返回就好啦~ #include<cstdio> #include<iostream> #define R register int #define ls (tr<<1) #define rs (tr<<1|1) using namespace std; inline long long g() { register long long ret=0,fix=1;

438D - The Child and Sequence

#include <stdio.h> #include <algorithm> using namespace std; #define lson num << 1 #define rson num << 1 | 1 #define MAXN 100005 typedef long long ll; int a[MAXN << 1]; struct node { int l,r; ll Max,sum; }tree[MAXN << 2