• CF438D 线段树 区间求和,区间求膜,单点更新


    题目链接

    题目大意:

    给定一个长度为n的序列,要求能够执行m次下列操作:

    1.查询区间[l,r]的和

    2.将区间[l,r]的每一个数%=mod

    3.修改第x个数为y

    操作1,3都是线段树的基本操作,线段树详细知识可以看看这篇大牛的文章   https://www.cnblogs.com/TheRoadToTheGold/p/6254255.html

    操作二取模如果一个个模那么复杂度为O(n*m),直接T,我们可以在线段树中同时维护一个最大值,如果一个区间的最大值比取模值要小,就可以不取模,否则的话递归左右子树,继续将每个区间

    的最大值与取模值进行比较,一直不断缩小到单点,使需要取模的单点才取模,这样就不会T了

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int inf=1<<30;
     4 typedef long long ll;
     5 const double pi=acos(-1);
     6 const int mod=1e9+7;
     7 const int maxn=1e5+7;
     8 int n,m;ll ans;
     9 struct node{
    10     int l,r,maxx;ll v;
    11 }tree[4*maxn];
    12 void modify(int k,int x,int y,int z){
    13     if(tree[k].maxx<z) return ;
    14     if(tree[k].l==tree[k].r){
    15         tree[k].v%=z;tree[k].maxx=tree[k].v;
    16         return ;
    17     }
    18     int m=(tree[k].l+tree[k].r)/2;
    19     if(x<=m) modify(2*k,x,y,z);
    20     if(y>m) modify(2*k+1,x,y,z);
    21     tree[k].v=tree[k*2].v+tree[2*k+1].v;
    22     tree[k].maxx=max(tree[k*2].maxx,tree[k*2+1].maxx);
    23 }
    24 void build(int l,int r,int k){
    25     //important
    26     tree[k].l=l,tree[k].r=r;
    27     if(l==r){
    28         scanf("%d",&tree[k].v);
    29         tree[k].maxx=tree[k].v;
    30         return ;
    31     }
    32     int m=(l+r)>>1;
    33     build(l,m,k*2);
    34     build(m+1,r,k*2+1);
    35     tree[k].v=tree[2*k].v+tree[2*k+1].v;
    36     tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx);
    37 }
    38 void sum(int k,int x,int y){
    39     if(tree[k].l>=x&&tree[k].r<=y){
    40         ans+=tree[k].v;    //cout<<111<<endl;
    41         return ;
    42     }
    43     int m=(tree[k].l+tree[k].r)/2;
    44     if(x<=m) sum(k*2,x,y);
    45     if(y>m) sum(k*2+1,x,y);
    46 }
    47 void change(int k,int x,int y){
    48     if(tree[k].l==tree[k].r){
    49         tree[k].v=y,tree[k].maxx=y;return;
    50     }
    51     int m=(tree[k].l+tree[k].r)/2;
    52     if(x<=m) change(k*2,x,y);
    53     else change(k*2+1,x,y);
    54     tree[k].v=tree[2*k].v+tree[2*k+1].v;
    55     tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx);
    56 }
    57 int main(){
    58     scanf("%d%d",&n,&m);
    59     build(1,n,1);
    60     while(m--){
    61         int type,x,y,z;scanf("%d%d%d",&type,&x,&y);
    62         if(type==1){
    63             ans=0;
    64             sum(1,x,y);
    65             printf("%lld
    ",ans);
    66         }
    67         else if(type==2){
    68             scanf("%d",&z);
    69             modify(1,x,y,z);
    70         }
    71         else if(type==3){
    72             change(1,x,y);
    73         }
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    测试工作中需要用到的一些linux命令
    软件的性能测试到底是测试哪些方面
    软件测试中的安全测试包括哪些方面
    git一不小心上传了大文件,怎么破?
    接口测试校验返回数据格式,JasonSchema使用详解
    selenium定位中需要鼠标悬浮才能显示的按钮
    jenknis参数化构建,windows和shell引用变量
    selenium元素定位之父子节点、胞节点
    selenium元素定位之多个元素中选择其中的一个
    Python实现注册和三次验证登录
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/10393209.html
Copyright © 2020-2023  润新知