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; register char ch; while(!isdigit(ch=getchar())) fix=ch==‘-‘?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m,M;
long long sum[400010],mx[400010],cnt[400010];
inline void upd(int tr) {sum[tr]=sum[ls]+sum[rs]; mx[tr]=max(mx[ls],mx[rs]);}
inline void build(int tr,int l,int r) {
    if(l==r) {mx[tr]=sum[tr]=g(); return ;}
    R md=(l+r)>>1; build(ls,l,md),build(rs,md+1,r); upd(tr);
}
inline void chg(int tr,int l,int r,int pos,int x) {
    if(l==r) {sum[tr]=mx[tr]=x; return ;} R md=(l+r)>>1;
    if(pos>md) chg(rs,md+1,r,pos,x);
    else chg(ls,l,md,pos,x); upd(tr);
}
inline void change(int tr,int l,int r,int LL,int RR) {
    if(mx[tr]<M) return ;
    if(l==r) {mx[tr]=sum[tr]=sum[tr]%M; return ;}
    R md=(l+r)>>1;
    if(LL>md) change(rs,md+1,r,LL,RR);
    else if(RR<md+1) change(ls,l,md,LL,RR);
    else change(ls,l,md,LL,md),change(rs,md+1,r,md+1,RR); upd(tr);
}
inline long long query(int tr,int l,int r,int LL,int RR) {
    if(l==LL&&r==RR) return sum[tr];
    R md=(l+r)>>1;
    if(LL>md) return query(rs,md+1,r,LL,RR);
    else if(RR<md+1) return query(ls,l,md,LL,RR);
    else return query(ls,l,md,LL,md)+query(rs,md+1,r,md+1,RR);
}
signed main() {
    n=g(),m=g(); build(1,1,n);
    for(R i=1,k,l,r;i<=m;++i) {
        k=g(),l=g(),r=g();
        if(k==1) printf("%lld\n",query(1,1,n,l,r));
        else if(k==2) M=g(),change(1,1,n,l,r);
        else chg(1,1,n,l,r);
    }
}


2019.04.18

原文地址:https://www.cnblogs.com/Jackpei/p/10731836.html

时间: 2024-08-29 11:45:14

CF438D The Child and Sequence 线段树的相关文章

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 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

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

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

hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

HDOJ 4893 Wow! Such Sequence! 线段树

http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:10万的区间,初始都为0,10万次操作,三种操作为单点修改,区间将每个数改成最近的斐波那契数,以及区间求和. 分析:用一个flag记录该段是否被改成斐波那契数,同时多维护一个sum1表示如果该段改成斐波那契数,区间和为多少.开始sum1为区间长度,之后在单点做了修改以后对其更新,需要的时候用其覆盖sum. 1 #include<cstdio> 2 #include<cstring>

HDU4893 Wow! Such Sequence! 线段树

题意:给你一个序列,其中有三种操作 1)位置为K 的数+ D 2)求 l-r 区间和 3)把 l-r 区间里面的所有数都变为理它最近的斐波纳契数 解题思路:这个题的区间更新其实可以在单点更新的时候就得出,为节点维护两个 和,一个是 斐波纳契和 一个是正常和 ,再看这个区间有没有被3覆盖,特判一下就行了. 解题代码: 1 // File Name: 1007.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月29日 星期二 12时49分33