题目链接

P2023 [AHOI2009]维护序列

解题思路

线段树板子。不难,但是...有坑。坑有多深?一页\(WA\)。

由于乘法可能乘\(k=0\),我这种做法可能会使结果产生负数。于是就有了这篇题解。

(详情见代码注释)

AC代码

#include<stdio.h>
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
typedef long long ll;
int n,m;
ll mod,k,a[500010];
struct Tree{
int left,right;
ll data,lazy,mul;
}tree[2000010];
void build(int p,int left,int right){
tree[p].left=left;
tree[p].right=right;
tree[p].mul=1;
if(left==right){tree[p].data=a[left];return;}
build(p<<1,left,(left+right)>>1);
build(p<<1|1,((left+right)>>1)+1,right);
tree[p].data=(tree[p<<1].data+tree[p<<1|1].data)%mod;
}
void pushdown(int p){
ll mul=tree[p].mul,lazy=tree[p].lazy;
tree[p<<1].lazy*=mul;
tree[p<<1].lazy+=lazy;tree[p<<1].lazy%=mod;
tree[p<<1].mul*=mul;tree[p<<1].mul%=mod;
tree[p<<1|1].lazy*=mul;
tree[p<<1|1].lazy+=lazy;tree[p<<1|1].lazy%=mod;
tree[p<<1|1].mul*=mul;tree[p<<1|1].mul%=mod;
tree[p].data*=tree[p].mul;
tree[p].data+=(tree[p].right-tree[p].left+1)*tree[p].lazy;
tree[p].data%=mod;
tree[p].lazy=0;tree[p].mul=1;
}
void add(int left,int right,ll k,int p){
int l=tree[p].left,r=tree[p].right;
if(l>right||r<left||p>4*n)return;
pushdown(p);
if(l>=left&&r<=right){
tree[p].lazy+=k;
tree[p].lazy%=mod;
return;
}
tree[p].data+=k*(min(right,r)-max(left,l)+1);
tree[p].data%=mod;
add(left,right,k,p<<1);
add(left,right,k,p<<1|1);
}
ll multy(int left,int right,ll k,int p){
int l=tree[p].left,r=tree[p].right;
if(l>right||r<left||p>4*n)return 0;
pushdown(p);
if(l>=left&&r<=right){
ll temp=tree[p].data*tree[p].mul+tree[p].lazy*(r-l+1);
tree[p].lazy*=k;tree[p].lazy%=mod;
tree[p].mul*=k;tree[p].mul%=mod;
return ((k-1)*temp%mod+mod)%mod;//非常重要!!!!!!
}
ll temp=multy(left,right,k,p<<1)+multy(left,right,k,p<<1|1);
tree[p].data+=temp;
tree[p].data=;
return temp;
}
ll query(int left,int right,int p){
int l=tree[p].left,r=tree[p].right;
if(l>right||r<left||p>4*n)return 0;
pushdown(p);
if(l>=left&&r<=right)return tree[p].data;
return query(left,right,p<<1)+query(left,right,p<<1|1);
}
int main(){
int s,x,y,i;
scanf("%d%lld",&n,&mod);
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
build(1,1,n);
scanf("%d",&m);
while(m--){
scanf("%d%d%d",&s,&x,&y);
if(s-3){
scanf("%lld",&k);
if(s-1)add(x,y,k,1);
else multy(x,y,k,1);
}else printf("%lld\n",query(x,y,1)%mod);
}
return 0;
}

最新文章

  1. 【夔堂】:程序血泪史之——有一种垃圾语言叫做JavaScript
  2. 关于webapi post 使用多个参数的间接用法
  3. 头像上传功能实现,PC端的需要做兼容
  4. 如何下载google play免费应用的apk文件
  5. 分布式服务框架:Zookeeper
  6. SPOJ #691. Hotel Floors
  7. Web Service学习之五:WSDL详解
  8. fiddler插件开发step by step 1
  9. sqlserver2005重新安装(安装汇编错误,安装程序无法连接到数据库服务进行服务配置)
  10. jsp:useBean的使用
  11. 201521123099 《Java程序设计》 第10周学习总结
  12. PHP中反射的简单实用(动态代理)
  13. webserver Etcd Cluster / CoreOS etcd / macOS etcd
  14. PL/SQL Developer如何导出数据成sql的insert语句
  15. 初窥RabbitMQ消息中间及SpringBoot整合
  16. hadoop分布式系统架构详解
  17. 包packages
  18. teamview修改id
  19. soapUI工具使用方法、简介、接口测试
  20. MySQL 5.6 Index Condition Pushdown

热门文章

  1. 二进制安装kubernetes(六) kube-proxy组件安装
  2. CSS 解决Float后塌陷问题
  3. DC1(msf drupal7+suid-find提权)
  4. VuePress &amp; Markdown Slot
  5. 24 Days Of JavaScript mas
  6. website i18n and L10n all in one
  7. trao 模拟点击 &amp; js auto click
  8. Taro Advanced
  9. 2021 NGK新机遇!---NGK生态所、星空计划双赛道爆发
  10. 投资者通过这几种方式可以快速在NGK赚取收益