zoukankan      html  css  js  c++  java
  • 关于线段树的一些问题

    啥叫线段树我觉得就不用写了,看一个板子吧  我线段树写得不好众所周知。。

    题目链接

    https://www.luogu.com.cn/problem/P3373

    注意事项

    来自洛谷的一道题,说是板子感觉好像跟那个行星序列差不多其实一样 , 但那道题我是边看着板子边打的,这次我决定自己打一下试试,于是我就凭着自己的感觉把线段树打了一遍,然后就是调试过程,这次调还好,没有什么特别大的问题,就是有一点引起了我的注意,pushdown的时候要不要进行更新,我当时想的是,pushdown完了儿子节点已经被更新,如果不更新一下父亲节点,就会出问题。

    实际上不是的,pushdown的标记是哪来的?是更新完父亲节点后push下来的,所以应该是父亲节点已经更新而儿子节点未更新,所以要pushdown保证访问的是正确的儿子信息,而乍一想在pushdown里边修改父亲节点好像也不会出问题,没错只是乍一想,写了后在数据很大的情况下会直接RE为什么?因为有可能你更新的是叶子节点,这样的话叶子就会被更新成0所以不能在这里更新。再有就是这道题按老师讲的做法来做把我自己搞懵了,一会儿push乘法一会儿push加法。。。。。所以我觉得可以换一个写法,乘和加一块push,如果修改乘法,那不就是+0嘛,修改加法,那不就是×1嘛,所以直接放到一起就好,这道题最大的收获还是写对了线段树找点自信 感觉像数据结构这一类的东西不要背模板,背了也没啥用,到时候一紧张忘了就白扯,所以要靠自己的理解去记忆,这样大不了到时候打错了还能自己调。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #define ll long long 
     6 using namespace std;
     7 const int N=1e5+10;
     8 struct Node{
     9     ll val,cheng,jia;
    10     Node(){cheng=1;jia=0;}
    11 }tree[N<<2];
    12 ll a[N],p;
    13 void Build(ll rt,ll l,ll r){
    14     if(l==r){
    15         tree[rt].val=a[l]%p;
    16         return;
    17     }
    18     ll mid=l+r>>1;
    19     Build(rt<<1,l,mid);
    20     Build(rt<<1|1,mid+1,r);
    21     tree[rt].val=(tree[rt<<1].val+tree[rt<<1|1].val)%p;
    22 }
    23 ll cr,cl;
    24 void updata(ll rt,ll l,ll r,ll w,ll k){
    25     tree[rt].val=(tree[rt].val*k%p+w*(r-l+1)%p)%p;
    26     tree[rt].jia=(tree[rt].jia*k%p+w)%p;
    27     tree[rt].cheng=tree[rt].cheng*k%p;
    28 }
    29 void pushdown(ll rt,ll l,ll r){
    30     ll mid=l+r>>1;
    31     updata(rt<<1,l,mid,tree[rt].jia,tree[rt].cheng);
    32     updata(rt<<1|1,mid+1,r,tree[rt].jia,tree[rt].cheng);
    33     tree[rt].cheng=1;tree[rt].jia=0;
    34 }
    35 void modify(ll rt,ll l,ll r,ll w,ll k){
    36     if(cr<l||cl>r)return;
    37     if(cr>=r&&cl<=l){
    38         updata(rt,l,r,w,k);
    39         return;
    40     }
    41     pushdown(rt,l,r);
    42     ll mid=l+r>>1;
    43     modify(rt<<1,l,mid,w,k);
    44     modify(rt<<1|1,mid+1,r,w,k);
    45     tree[rt].val=(tree[rt<<1].val+tree[rt<<1|1].val)%p;
    46 }
    47 ll query(ll rt,ll l,ll r){
    48     if(l>=cl&&r<=cr){
    49         tree[rt].val%=p;
    50         return tree[rt].val;
    51     }
    52     int mid=l+r>>1;
    53     pushdown(rt,l,r);
    54     ll ans=0;
    55     if(cl<=mid)ans=(ans+query(rt<<1,l,mid))%p;
    56     if(cr>mid)ans=(ans+query(rt<<1|1,mid+1,r))%p;
    57     return ans;
    58 }
    59 int main(){
    60     int m,n;
    61     scanf("%d%d%lld",&n,&m,&p);
    62     for(int i=1;i<=n;i++)
    63         scanf("%d",&a[i]);
    64     Build(1,1,n);
    65     for(int i=1;i<=m;i++){
    66         ll num,type;
    67         scanf("%lld%lld%lld",&type,&cl,&cr);
    68         if(type==1){
    69             scanf("%lld",&num);
    70             modify(1,1,n,0,num);
    71         }
    72         else if(type==2){
    73             scanf("%lld",&num);
    74             modify(1,1,n,num,1);
    75         }else{
    76             printf("%lld
    ",query(1,1,n)%p);
    77         } 
    78     }
    79     return 0;
    80 }

    依旧是不开long long见祖宗,开个longlong又不费时间,能开尽量就开,别最后再改,万一你最后忘了呢?而且写个ll还比int少写一个字符,好吧这是次要的

  • 相关阅读:
    android开发环境搭建日记和嵌入式Android开发环境初探
    QT210 android2.3 和android4.0 烧写编译日记
    RAM,SRAM,DRAM,SDRAM,DDR RAM,ROM,PROM,EPROM,EEPROM,NAND FLASH,NOR FLASH的区别
    如何修改终端用户名颜色修改为红色(可以自由定制)
    FPGA机器学习之stanford机器学习第三堂2
    FPGA机器学习之stanford机器学习第三堂1
    FPGA机器学习之stanford机器学习第二堂2
    FPGA机器学习之stanford机器学习第二堂1
    FPGA机器学习之stanford机器学习第一堂
    FPGA片外存储器ddr2之DQSn引脚的分析
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12459388.html
Copyright © 2011-2022 走看看