• SPOJ DCEPC11I


    题目大意:

    就是给定一段区间令其中的数增加一个递增序列(也就是说第一个+1,第二个+2.。。。。)

    询问操作是区间的和

    这里的查询很简单,但是对于添加递增序列入区间就比较搞脑子了

    我们需要一个add[]作为区间的首个数字增加的值,del[]表示等差数列的公差,因为你每次添加进入一个等差数列,是可以叠加的但公差变为了del[ls]+=del[o]

    这里主要是pushdown函数的写法

    我们要用到等差公式的求和:S =a*n+n(n-1)*d/2

    void push_down(int o,int x,int y)
    {
        int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
        if(add[o]||del[o]){
            int t1=mid-x+1,t2=y-mid;
            LL a2=add[o]+t1*del[o];
            sum[ls]+=add[o]*t1+t1*(t1-1)*del[o]/2;
            sum[rs]+=a2*t2+t2*(t2-1)*del[o]/2;
            add[ls]+=add[o],add[rs]+=a2;
            del[ls]+=del[o],del[rs]+=del[o];
            add[o]=del[o]=0;
        }
    }

    总代码如下所示:

     1 #include <cstdio>
     2 #include <cstring>
     3 using namespace std;
     4 #define L ls,x,mid
     5 #define R rs,mid+1,y
     6 #define LL long long
     7 #define N 100010
     8 LL sum[N<<2],add[N<<2];
     9 int del[N<<2];
    10 void push_up(int o)
    11 {
    12     sum[o]=sum[o<<1]+sum[o<<1|1];
    13 }
    14 void push_down(int o,int x,int y)
    15 {
    16     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
    17     if(add[o]||del[o]){
    18         int t1=mid-x+1,t2=y-mid;
    19         LL a2=add[o]+t1*del[o];
    20         sum[ls]+=add[o]*t1+t1*(t1-1)*del[o]/2;
    21         sum[rs]+=a2*t2+t2*(t2-1)*del[o]/2;
    22         add[ls]+=add[o],add[rs]+=a2;
    23         del[ls]+=del[o],del[rs]+=del[o];
    24         add[o]=del[o]=0;
    25     }
    26 }
    27 void build(int o,int x,int y)
    28 {
    29     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
    30     sum[o]=del[o]=add[o]=0;
    31     if(x==y) return;
    32     build(L);
    33     build(R);
    34 }
    35 void update(int o,int x,int y,int s,int t)
    36 {
    37     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
    38     if(x>=s&&y<=t){
    39         add[o]+=x-s+1;
    40         sum[o]+=(x-s+1)*(y-x+1)+(y-x+1)*(y-x)/2;
    41         del[o]++;
    42         return;
    43     }
    44     push_down(o,x,y);
    45     if(mid>=s) update(L,s,t);
    46     if(mid<t) update(R,s,t);
    47     push_up(o);
    48 }
    49 void query(int o,int x,int y,int s,int t,LL &ans)
    50 {
    51     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
    52     if(x>=s&&y<=t){
    53         ans+=sum[o];
    54         return;
    55     }
    56     push_down(o,x,y);
    57     if(mid>=s) query(L,s,t,ans);
    58     if(mid<t) query(R,s,t,ans);
    59 }
    60 int main()
    61 {
    62     int n,q,op,a,b;
    63     scanf("%d%d",&n,&q);
    64     build(1,1,n);
    65     for(int i=0;i<q;i++){
    66         scanf("%d%d%d",&op,&a,&b);
    67         if(op){
    68             LL ans=0;
    69             query(1,1,n,a,b,ans);
    70             printf("%lld
    ",ans);
    71         }
    72         else update(1,1,n,a,b);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    通过Logstash由SQLServer向Elasticsearch同步数据
    ELK +Nlog 分布式日志系统的搭建 For Windows
    Gulp 给所有静态文件引用加版本号
    Fluentdata详解
    jQuery Easy UI (适应屏幕分辨率大小)布局(Layout)
    什么是数据结构---算法
    WCF的学习之旅
    程序员必学之精华----软件工程
    译 .NET Core 3.0 发布
    Vue+Element UI 实现视频上传
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/3901222.html
Copyright © 2020-2023  润新知