码迷,mamicode.com
首页 > 其他好文 > 详细

cogs 2632. [HZOI 2016] 数列操作d

时间:2019-08-06 14:00:16      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:限制   标记   格式   ++   long   sele   操作   int   mes   

2632. [HZOI 2016] 数列操作d

★★★   输入文件:segment.in   输出文件:segment.out   简单对比
时间限制:3 s   内存限制:512 MB

【题目描述】

一个长度为n的序列,一开始序列数的权值都是0,有m次操作

支持两种操作:

1 L R x,给区间[L,R]内位置为pos的数加上(pos-L)*x

0 L R,查询区间[L,R]内的权值和

最终答案对109+7取模。

【输入格式】

第一行两个数n,m,表示序列长度和操作次数

接下来m行,每行描述一个操作,有如下两种情况:

1 L R x,给区间[L,R]内位置为pos的数加上(posL)×x

0 L R,查询区间[L,R]内的权值和

【输出格式】

每一个0操作输出一个整数模109+7

【样例输入】

5 5
0 2 3
1 4 5 1
1 1 5 5
0 1 4
0 2 3

【样例输出】

0
30
15 

【提示】

对于30%的数据 n,m<=2000

对于100%的数据,n,m<=300000

保证读入的都是非负整数,所有的x<=10000

【来源】

感谢神犇
非常感谢神犇

非常非常感谢神犇

 

 
   

 

 

 

#include<bits/stdc++.h>
#define ll long long
#define INF 1000000007
#define maxn 300005
using namespace std;
ll S[maxn];
ll lz1[maxn<<2],lz2[maxn<<2];//lz1 就是记录那个-L *x的  lz2就是记录 pos*x的  
ll dat[maxn<<2];
void Add(int rt,int l,int r,int ss,int tt,ll qx,ll posx){ 
    if(ss>r||tt<l) return;//判断是否越界 
    if(ss<=l&&r<=tt){//全部包含 
        lz1[rt]=(lz1[rt]+qx)%INF;//永久化标记 
        lz2[rt]=(lz2[rt]+posx)%INF;
        dat[rt]=(dat[rt]+qx*(r-l+1)%INF+posx*((S[r]-S[l-1])%INF)%INF)%INF;// (S[r]-S[l-1])就是那一段等差数列的和 预处理出来了直接作一个差就行了  
        return;
    }
    int mid=(l+r)>>1;
    Add(rt*2,l,mid,ss,tt,qx,posx);Add(rt*2+1,mid+1,r,ss,tt,qx,posx);
    dat[rt]=(dat[rt*2]+dat[rt*2+1]+lz1[rt]*(r-l+1)%INF+lz2[rt]*((S[r]-S[l-1])%INF)%INF)%INF;
}
ll Get(int rt,int l,int r,int ss,int tt){
    if(ss>r||tt<l) return 0;
    if(ss<=l&&r<=tt) return dat[rt];
      int lll=max(l,ss);
    int rr=min(r,tt);
    int mid=(l+r)>>1;
    return (lz1[rt]*(rr-lll+1)%INF+lz2[rt]*((S[rr]-S[lll-1])%INF)%INF+Get(rt*2,l,mid,ss,tt)+Get(rt*2+1,mid+1,r,ss,tt))%INF;
}
int main(){
    freopen("segment.in","r",stdin);freopen("segment.out","w",stdout);
    int n,m;scanf("%d%d",&n,&m);//输入 不说了 哈哈 
    for(int i=1;i<=n;i++) S[i]=S[i-1]+i;//这里就是预处理一个前缀和 
    for(int i=1;i<=m;i++){
        int Type;scanf("%d",&Type);
        if(Type){
            int l,r;ll x,posx;scanf("%d%d%lld",&l,&r,&x);
            posx=(INF-l)*x%INF;//posx 就是那个-L  这里加上一个INF 是因为——L是负数  会炸的!! 
            Add(1,1,n,l,r,posx,x);
        }
        else{
            int l,r;scanf("%d%d",&l,&r);
            printf("%lld\n",Get(1,1,n,l,r)%INF);
        }
    }
    return 0;
}

 

cogs 2632. [HZOI 2016] 数列操作d

标签:限制   标记   格式   ++   long   sele   操作   int   mes   

原文地址:https://www.cnblogs.com/Tidoblogs/p/11308218.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!