P2023 [AHOI2009]维护序列

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

输入输出格式

输入格式:

第一行两个整数N和P(1≤P≤1000000000)。第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。第三行有一个整数M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

输出格式:

对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

输入输出样例

输入样例#1:

7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

输出样例#1:

2
35
8

说明

【样例说明】

初始时数列为(1,2,3,4,5,6,7)。

经过第1次操作后,数列为(1,10,15,20,25,6,7)。

对第2次操作,和为10+15+20=45,模43的结果是2。

经过第3次操作后,数列为(1,10,24,29,34,15,16}

对第4次操作,和为1+10+24=35,模43的结果是35。

对第5次操作,和为29+34+15+16=94,模43的结果是8。

测试数据规模如下表所示

数据编号 1 2 3 4 5 6 7 8 9 10

N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

Source: Ahoi 2009

调了一个半小时,调不出来

不调了、、

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define lli long long 
  7 using namespace std;
  8 const int MAXN=500001;
  9 lli n,m,mod,ans;
 10 void read(lli & n)
 11 {
 12     char c='+';lli x=0;bool flag=0;
 13     while(c<'0'||c>'9')
 14     {c=getchar();if(c=='-')flag=1;}
 15     while(c>='0'&&c<='9')
 16     {x=x*10+(c-48),c=getchar();}
 17     flag==1?n=-x:n=x;
 18 }
 19 struct node
 20 {
 21     lli l,r,w,k,fc,fj;
 22 }tree[MAXN*4];
 23 void pushdown(lli k,lli ll,lli rr,lli mid)
 24 {
 25     tree[k<<1].w*=tree[k].fc%mod;
 26     tree[k<<1|1].w*=tree[k].fc%mod;
 27     tree[k<<1].w=(tree[k<<1].w+tree[k].fj*(mid-ll+1))%mod;
 28     tree[k<<1|1].w=(tree[k<<1|1].w+tree[k].fj*(rr-mid))%mod;
 29     
 30     tree[k<<1].fc%=mod;tree[k<<1|1].fc%=mod;
 31     tree[k<<1].fj%=mod;tree[k<<1|1].fj%=mod;
 32     tree[k<<1].w%=mod;tree[k<<1|1].w%=mod;
 33     
 34     tree[k<<1].fc*=tree[k].fc%mod;tree[k<<1|1].fc*=tree[k].fc%mod;
 35     tree[k<<1].fj*=tree[k].fc%mod;tree[k<<1|1].fj*=tree[k].fc%mod;
 36     tree[k<<1].fj=(tree[k<<1].fj+tree[k].fj)%mod;
 37     tree[k<<1|1].fj=(tree[k<<1|1].fj+tree[k].fj)%mod;
 38     
 39     
 40     tree[k].fc=1;
 41     tree[k].fj=0;
 42     
 43     
 44     tree[k<<1].fc%=mod;tree[k<<1|1].fc%=mod;
 45     tree[k<<1].fj%=mod;tree[k<<1|1].fj%=mod;
 46     tree[k<<1].w%=mod;tree[k<<1|1].w%=mod;
 47 }
 48 void update(lli k)
 49 {
 50     tree[k].w=(tree[k<<1].w+tree[k<<1|1].w)%mod;
 51 }
 52 void build_tree(lli ll,lli rr,lli k)
 53 {
 54     tree[k].l=ll;tree[k].r=rr;tree[k].k=k;
 55     tree[k].fc=1;tree[k].fj=0;
 56     if(tree[k].l==tree[k].r)
 57     {
 58         read(tree[k].w);
 59         tree[k].w%=mod;
 60         return ;
 61     }
 62     lli mid=(ll+rr)>>1;
 63     build_tree(ll,mid,k<<1);
 64     build_tree(mid+1,rr,k<<1|1);
 65     update(k);
 66 }
 67 void interval_mul(lli k,lli ll,lli rr,lli v)
 68 {
 69     if(ll>tree[k].r||rr<tree[k].l)
 70     return ;
 71     if(tree[k].l>=ll&&tree[k].r<=rr)
 72     {
 73         tree[k].w*=v%mod;
 74         tree[k].fc*=v%mod;
 75         tree[k].fj*=v%mod;
 76         return ;
 77     }
 78     lli mid=(tree[k].l+tree[k].r)>>1;
 79     pushdown(k,tree[k].l,tree[k].r,mid);
 80     if(ll<=mid)
 81         interval_mul(k<<1,ll,rr,v);
 82     if(rr>mid)
 83         interval_mul(k<<1|1,ll,rr,v);
 84     update(k);
 85 }
 86 void interval_add(lli k,lli ll,lli rr,lli v)
 87 {
 88     if(ll>tree[k].r||rr<tree[k].l)
 89     return ;
 90     if(tree[k].l>=ll&&tree[k].r<=rr)
 91     {
 92         tree[k].w=(tree[k].w+v*(tree[k].r-tree[k].l+1))%mod;
 93         //tree[k].fc*=v%mod;
 94         tree[k].fj=(tree[k].fj+v)%mod;
 95         return ;
 96     }
 97     lli mid=(tree[k].l+tree[k].r)>>1;
 98     pushdown(k,tree[k].l,tree[k].r,mid);
 99     if(ll<=mid)
100         interval_add(k<<1,ll,rr,v);
101     if(rr>mid)
102         interval_add(k<<1|1,ll,rr,v);
103     update(k);
104 
105 }
106 void interval_ask(lli k,lli ll,lli rr)
107 {
108     if(ll>tree[k].r||rr<tree[k].l)
109     return ;
110     if(tree[k].l>=ll&&tree[k].r<=rr)
111     {
112         ans=(ans+tree[k].w)%mod;
113         return ;
114     }
115     lli mid=(tree[k].l+tree[k].r)>>1;
116     pushdown(k,tree[k].l,tree[k].r,mid);
117     if(ll<=mid)
118         interval_ask(k<<1,ll,rr);
119     if(rr>mid)
120         interval_ask(k<<1|1,ll,rr);
121     update(k);
122 }
123 int main()
124 {
125     read(n);read(mod);
126     build_tree(1,n,1);
127     read(m);
128     for(lli i=1;i<=m;i++)
129     {
130         lli how,x,y,c;
131         read(how);
132         if(how==1)
133         {
134             read(x);read(y);read(c);
135             interval_mul(1,x,y,c%mod);//乘 
136         }
137         else if(how==2)
138         {
139             read(x);read(y);read(c);
140             interval_add(1,x,y,c%mod);// 加 
141         }
142         else if(how==3)
143         {
144             ans=0;
145             read(x);read(y);
146             interval_ask(1,x,y);
147             printf("%lld\n",ans);
148         }
149     }
150     return 0;
151 }
 1 #include<iostream>
 2 #include<cstdio>
 3 #define lli long long int 
 4 #define re register
 5 #define LL long long
 6 #define M 500000
 7 using namespace std;
 8 void read(lli & n)
 9 {
10     char c='+';lli x=0;bool flag=0;
11     while(c<'0'||c>'9')
12     {c=getchar();if(c=='-')flag=1;}
13     while(c>='0'&&c<='9')
14     {x=x*10+(c-48),c=getchar();}
15     flag==1?n=-x:n=x;
16 }
17 LL mogician,a[M/2+1];
18 int n;
19 struct Tree{
20     LL sum,add,mult;
21 }tr[M+1];
22 inline void build(int k,int l,int r){
23     tr[k].mult=1;
24     if(l==r){
25         tr[k].sum=a[l];
26         return ;
27     }
28     int mid=(l+r)>>1;
29     build(k<<1,l,mid);
30     build(k<<1|1,mid+1,r);
31     tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum)%mogician;
32 }
33 inline void Work_Out(int k,int l,int r,LL mu,LL ad){
34     tr[k].add=(tr[k].add*mu+ad)%mogician;
35     tr[k].mult=(tr[k].mult*mu)%mogician;
36     tr[k].sum=(tr[k].sum*mu+(r-l+1)*ad)%mogician;
37 }
38 inline void Push_Down(int k,int l,int r){
39     if(tr[k].add==0&&tr[k].mult==1)
40         return ;
41     int mid=(l+r)>>1;
42     Work_Out(k<<1,l,mid,tr[k].mult,tr[k].add);
43     Work_Out(k<<1|1,mid+1,r,tr[k].mult,tr[k].add);
44     tr[k].add=0;
45     tr[k].mult=1;
46 }
47 inline void Lazy_Tag(int k,int l,int r,int x,int y,LL mu,LL ad){
48     if(x<=l&&r<=y){
49         Work_Out(k,l,r,mu,ad);
50         return ;
51     }
52     Push_Down(k,l,r);
53     int mid=(l+r)>>1;
54     if(x<=mid)
55         Lazy_Tag(k<<1,l,mid,x,y,mu,ad);
56     if(mid<y)
57         Lazy_Tag(k<<1|1,mid+1,r,x,y,mu,ad);
58     tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum)%mogician;
59 }
60 inline LL Q(int k,int l,int r,int x,int y){
61     if(x<=l&&r<=y)
62         return tr[k].sum%mogician;
63     Push_Down(k,l,r);
64     int mid=(l+r)>>1;
65     return    ((x<=mid?Q(k<<1,l,mid,x,y)%mogician:0)+(mid<y?Q(k<<1|1,mid+1,r,x,y)%mogician:0))%mogician;
66 }
67 int m,d,x,y;
68 LL k;
69 int main(){
70     
71     scanf("%lld%lld",&n,&mogician);
72     for(re int i=1;i<=n;i++){
73         scanf("%lld",&a[i]);
74         a[i]%=mogician;
75     }
76     build(1,1,n);
77     scanf("%d",&m);
78     for(re int i=1;i<=m;i++){
79         scanf("%d%d%d",&d,&x,&y);
80         if(d==3)
81             printf("%lld\n",Q(1,1,n,x,y));
82         else{
83             scanf("%lld",&k);
84             k%=mogician;
85             d==1?Lazy_Tag(1,1,n,x,y,k,0):Lazy_Tag(1,1,n,x,y,1,k);
86         }
87     }
88     return 0;
89 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏noteless

[三]基础数据类型之Integer详解

2253
来自专栏程序猿DD

第三章 正则表达式括号的作用

第三章 正则表达式括号的作用 不管哪门语言中都有括号。正则表达式也是一门语言,而括号的存在使这门语言更为强大。 对括号的使用是否得心应手,是衡量对正则的掌握水平...

2696
来自专栏nummy

python堆排序heapq

堆是一种树形数据结构,其中子节点与父节点之间是一种有序关系。最大堆中父节点大于或等于两个子节点,最小堆父节点小于或等于两个子节点。Python的heapq模块实...

2413
来自专栏技术沉淀

Python: collections模块实例透析Collections模块

1898
来自专栏武培轩的专栏

排序算法-插入排序

算法简介 插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应...

2764
来自专栏IT可乐

Java数据结构和算法(六)——前缀、中缀、后缀表达式

  前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆...

2619
来自专栏Python中文社区

Python函数的基本特征详解

今天开始,我们来讲讲函数,简而言之一个函数就是将一些语句集合在一起的部件,它们能够不止一次的在程序中运行。函数还能计算出一个返回值,并能够改变作为函数输入的参数...

1324
来自专栏数据结构与算法

1497 取余运算

1497 取余运算 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 输入...

3417
来自专栏武培轩的专栏

Leetcode#557. Reverse Words in a String III(反转字符串中的单词 III)

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

773
来自专栏Java爬坑系列

【JAVA零基础入门系列】Day10 Java中的数组

  什么是数组?顾名思义,就是数据的组合,把一些相同类型的数放到一组里去。   那为什么要用数组呢?比如需要统计全班同学的成绩的时候,如果给班上50个同学的成绩...

2136

扫码关注云+社区

领取腾讯云代金券