zoukankan      html  css  js  c++  java
  • BZOJ1798: [Ahoi2009]Seq 维护序列seq

    题目链接:

      TP

    題解:

      线段树玩法真心多233

      以前见过类似的题,但没写,今天做LCT发现一道双修改,尴尬的发现自己不太会2333,然后zyf就一脸嫌弃的告诉我先写这道线段树的版本emmmmmmm

      自己YY了好久,发现总会被时间顺序日到……看了题解(我是大蒟蒻……

      因为我一直都想把两种操作分离开,事实上没必要,因为发现对于已经加过的数值$plus$,假设我们没有将这个值传下去,那么下次修改时,若我们将其乘上一个数$mul$,事实上按照时间顺序,我们其实也要把该值乘上$mul$。所以我们可以直接将$plus$乘上$mul$,等到以后再传下去。这样我们就有效的干掉了时间顺序。

    代码:

     1 #define Troy
     2 
     3 #include "bits/stdc++.h"
     4 
     5 using namespace std;
     6 
     7 const int N=1e5+5;
     8 
     9 inline int read(){
    10     int s=0,k=1;char ch=getchar();
    11     while(ch<'0'|ch>'9')    ch=='-'?k=-1:0,ch=getchar();
    12     while(ch>47&ch<='9')    s=s*10+(ch^48),ch=getchar();
    13     return s*k;
    14 }
    15 
    16 int n,p,m;
    17 
    18 struct Tree{
    19     int sum,mul,plu;
    20     Tree *lc,*rc;
    21     Tree(){sum=plu=0,mul=1;lc=rc=NULL;}
    22 }*root,tree[N<<2];int cnt;
    23 
    24 inline void build(Tree *&u,int l,int r){
    25     u=tree+cnt,++cnt;
    26     if(l==r){
    27         u->sum=read();return;
    28     }int mid=l+r>>1;
    29     build(u->lc,l,mid);
    30     build(u->rc,mid+1,r);
    31     u->sum=(u->lc->sum+u->rc->sum)%p;
    32 }
    33 
    34 inline void push(Tree *u,int leth,int mul,int plu){
    35     u->sum=(u->sum*1ll*mul+plu*1ll*(leth))%p;
    36     u->mul=u->mul*1ll*mul%p;
    37     u->plu=(u->plu*1ll*mul+plu)%p;
    38 }   
    39 
    40 inline void pushdown(Tree *u,int l,int r){
    41     int mid=l+r>>1;
    42     push(u->lc,mid-l+1,u->mul,u->plu);
    43     push(u->rc,r-mid,u->mul,u->plu);
    44     u->mul=1,u->plu=0;
    45 }
    46 
    47 inline void update_1(Tree *u,int l,int r,int x,int y,int val){
    48     if(x<=l&&r<=y){
    49         u->mul=(u->mul*1ll*val)%p;
    50         u->plu=(u->plu*1ll*val)%p;
    51         u->sum=(u->sum*1ll*val)%p;
    52         return ;
    53     }
    54     int mid=l+r>>1;
    55     pushdown(u,l,r);
    56     if(y>mid)   update_1(u->rc,mid+1,r,x,y,val);
    57     if(x<=mid)    update_1(u->lc,l,mid,x,y,val);
    58     u->sum=(u->lc->sum+u->rc->sum)%p;
    59 }
    60 
    61 inline void update_2(Tree *u,int l,int r,int x,int y,int val){
    62     if(x<=l&&r<=y){
    63         u->plu=(u->plu*1ll+val)%p;
    64         u->sum=(u->sum+1ll*val*(r-l+1))%p;
    65         return ;
    66     }
    67     int mid=l+r>>1;
    68     pushdown(u,l,r);
    69     if(y>mid)   update_2(u->rc,mid+1,r,x,y,val);
    70     if(x<=mid)    update_2(u->lc,l,mid,x,y,val);
    71     u->sum=(u->lc->sum+u->rc->sum)%p;
    72 }
    73 
    74 inline int query(Tree *u,int l,int r,int x,int y){
    75     if(x<=l&&r<=y)  return u->sum;
    76     pushdown(u,l,r);
    77     int mid=l+r>>1,ret=0;
    78     if(x<=mid)  ret=query(u->lc,l,mid,x,y);
    79     if(y>mid)   ret=(ret+query(u->rc,mid+1,r,x,y))%p;
    80     return ret;
    81 }
    82 
    83 int main(){
    84     n=read(),p=read();
    85     build(root,1,n);
    86     m=read()+1;
    87     register int opt,x,y,val;
    88     while(--m){
    89         opt=read();
    90         x=read(),y=read();
    91         if(opt!=3)  val=read()%p;
    92         switch(opt){
    93             case 1:update_1(root,1,n,x,y,val);break;
    94             case 2:update_2(root,1,n,x,y,val);break;
    95             case 3:printf("%d
    ",query(root,1,n,x,y));
    96         }
    97     }
    98 }
  • 相关阅读:
    cpp学习
    7-2 求逆序对数目 (20分) 归并排序 O(nlogn)
    Egret 滚动背景图的实现
    Egret-我的疑问:Scroller如何禁止水平或垂直方向滚动
    Egret-我的探索:exml自定义组件中通过ID获取子组件实例
    Egret-我的疑问:自定义组件加载skin的操作
    Egret事件冒泡的应用
    Egret点击穿透(使遮盖可点击组件的其他组件禁止点击)
    Egret wing 4.1.6项目目录结构
    Egret分步加载资源改写loading界面
  • 原文地址:https://www.cnblogs.com/Troywar/p/8044641.html
Copyright © 2011-2022 走看看