zoukankan      html  css  js  c++  java
  • codevs4927 线段树练习5

    题目描述 Description

    有n个数和5种操作

    add a b c:把区间[a,b]内的所有数都增加c

    set a b c:把区间[a,b]内的所有数都设为c

    sum a b:查询区间[a,b]的区间和

    max a b:查询区间[a,b]的最大值

    min a b:查询区间[a,b]的最小值

    输入描述 Input Description

    第一行两个整数n,m,第二行n个整数表示这n个数的初始值

    接下来m行操作,同题目描述

    输出描述 Output Description

    对于所有的sum、max、min询问,一行输出一个答案

    样例输入 Sample Input

    10 6

    3 9 2 8 1 7 5 0 4 6

    add 4 9 4

    set 2 6 2

    add 3 8 2

    sum 2 10

    max 1 7

    min 3 6

    样例输出 Sample Output

    49

    11

    4

    数据范围及提示 Data Size & Hint

    10%:1<n,m<=10

    30%:1<n,m<=10000

    100%:1<n,m<=100000

    保证中间结果在long long(C/C++)、int64(pascal)范围内

     


    正解:线段树

    解题报告:

      这就是传说中的线段树综合题,所有标记都有。

      注意一点,就是我的执行顺序是先add标记下传,然后才是set标记下传,但下传过程中set可以覆盖add。开始我一直WA,后来才发现了一个错误,就是我先执行的add,那么,如果当前结点上此时既有set又有add,那么只能说明add一定是在set之后执行的,不然执行set的时候add早已经下传,所以我可以考虑直接把add的值直接加在set上去,就可以避免有一部分add没有发挥作用。害得我调试了半个小时。

     

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 using namespace std;
     14 typedef long long LL;
     15 #define RG register
     16 const int MAXN = 100011;
     17 int n,m,ql,qr;
     18 LL val,ans,inf;
     19 char ch[10];
     20 struct node{
     21     int l,r;
     22     LL minl,maxl,sum,add,set;
     23     bool flag;
     24 }a[MAXN*3];
     25 
     26 inline LL getint(){RG LL w=0,q=0; char c=getchar();while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar();while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;}
     27 
     28 inline void update(RG int root){
     29     RG int lc=root*2,rc=lc+1;  a[root].maxl=max(a[lc].maxl,a[rc].maxl);
     30     a[root].sum=a[lc].sum+a[rc].sum;  a[root].minl=min(a[lc].minl,a[rc].minl);
     31 }
     32 
     33 inline void build(RG int root,RG int l,RG int r){
     34     a[root].l=l; a[root].r=r;
     35     if(l==r) {    a[root].minl=a[root].maxl=a[root].sum=getint();    return ;  }
     36     RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1;
     37     build(lc,l,mid); build(rc,mid+1,r); update(root);
     38 }
     39 
     40 inline void pushdown(int root,int l,int r){
     41     if(!a[root].flag) return ; if(l==r) { a[root].flag=false; a[root].set=0; return ; }
     42     int lc=root*2,rc=lc+1; int mid=(l+r)/2;
     43     a[lc].set=a[rc].set=a[root].set; a[root].add=a[lc].add=a[rc].add=0;
     44     a[lc].maxl=a[rc].maxl=a[lc].minl=a[rc].minl=a[root].set;
     45     a[lc].sum=(LL)(mid-l+1)*a[root].set; a[rc].sum=(LL)(r-mid)*a[root].set;  a[root].sum=a[lc].sum+a[rc].sum;
     46     a[lc].flag=a[rc].flag=true;
     47     a[root].set=0; a[root].flag=false;
     48 }
     49 
     50 inline void pushdown_add(RG int root,RG int l,RG int r){
     51     if(l==r) { a[root].add=0; return ; } if(a[root].add==0) return ;
     52  
     53     if(a[root].flag){ a[root].set+=a[root].add; a[root].add=0; return ; }//至关重要,因为add打在set的后面,这就意味着相当于我们可以把set设的值变大一点
     54 
     55     RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; a[lc].add+=a[root].add; a[rc].add+=a[root].add;    
     56     a[lc].minl+=a[root].add; a[lc].maxl+=a[root].add; a[rc].minl+=a[root].add; a[rc].maxl+=a[root].add;
     57     a[lc].sum+=a[root].add*(LL)(mid-l+1); a[rc].sum+=a[root].add*(LL)(r-mid);
     58     a[root].add=0; a[root].sum=a[lc].sum+a[rc].sum;
     59 }
     60 
     61 inline void add(RG int root,RG int l,RG int r){
     62     pushdown_add(root,l,r); pushdown(root,l,r); 
     63     if(ql<=l && r<=qr) { a[root].add+=val; a[root].maxl+=val; a[root].minl+=val; a[root].sum+=val*(LL)(r-l+1); return ; }
     64     RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; if(ql<=mid) add(lc,l,mid); if(qr>mid) add(rc,mid+1,r);
     65     update(root);
     66 }
     67 
     68 inline void update_set(RG int root,RG int l,RG int r){    
     69     if(ql<=l && r<=qr) { a[root].flag=true; a[root].minl=a[root].maxl=a[root].set=val; a[root].add=0; a[root].sum=(LL)(r-l+1)*val; return ; } 
     70     pushdown_add(root,l,r); pushdown(root,l,r);
     71     RG int mid=(l+r)/2;RG int lc=root*2,rc=lc+1;
     72     if(ql<=mid) update_set(lc,l,mid); if(qr>mid) update_set(rc,mid+1,r); update(root);
     73 }
     74 
     75 inline void query_sum(RG int root,RG int l,RG int r){
     76     pushdown_add(root,l,r);  pushdown(root,l,r);
     77     if(ql<=l && r<=qr){ ans+=a[root].sum; return ; }
     78     RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; 
     79     if(ql<=mid) query_sum(lc,l,mid); if(qr>mid) query_sum(rc,mid+1,r); update(root);
     80 }
     81 
     82 inline void query_max(RG int root,RG int l,RG int r){
     83     pushdown_add(root,l,r); pushdown(root,l,r);
     84     if(ql<=l && r<=qr){ ans=max(a[root].maxl,ans); return ; }
     85     RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; 
     86     if(ql<=mid) query_max(lc,l,mid); if(qr>mid) query_max(rc,mid+1,r); update(root);
     87 }
     88 
     89 inline void query_min(RG int root,RG int l,RG int r){
     90     pushdown_add(root,l,r); pushdown(root,l,r);
     91     if(ql<=l && r<=qr){ ans=min(a[root].minl,ans); return ; }
     92     RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; 
     93     if(ql<=mid) query_min(lc,l,mid); if(qr>mid) query_min(rc,mid+1,r); update(root);
     94 }
     95 
     96 inline void work(){
     97     n=getint(); m=getint(); build(1,1,n); inf=1; for(RG int i=1;i<=62;i++) inf*=2;
     98     while(m--) {
     99     scanf("%s",ch);
    100     if(ch[0]=='a') { ql=getint(); qr=getint(); val=getint(); add(1,1,n); }
    101     else if(ch[0]=='s' && ch[1]=='e') { ql=getint(); qr=getint(); val=getint(); update_set(1,1,n); }
    102     else if(ch[0]=='s' && ch[1]=='u') { ql=getint(); qr=getint(); ans=0; query_sum(1,1,n); printf("%lld
    ",ans); }
    103     else if(ch[0]=='m' && ch[1]=='a') { ql=getint(); qr=getint(); ans=-inf; query_max(1,1,n); printf("%lld
    ",ans); }
    104     else{ ql=getint(); qr=getint(); ans=inf; query_min(1,1,n); printf("%lld
    ",ans); }
    105     }
    106 }
    107 
    108 int main()
    109 {
    110   work();
    111   return 0;
    112 }
  • 相关阅读:
    Android签名详解(debug和release)
    Java反射机制的学习
    Android应用开发中如何使用隐藏API(转)
    asp.net购物车,订单以及模拟支付宝支付(二)---订单表
    asp.net购物车,订单以及模拟支付宝支付(一)---购物车表及添加购物车流程
    asp.net权限控制的方式
    .Net使用程序发送邮件时的问题
    Word2016“此功能看似已中断 并需要修复”问题解决办法
    C#字符串来袭——因为爱,所以爱
    C#时间的味道——任时光匆匆我只在乎你
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5879470.html
Copyright © 2011-2022 走看看