BZOJ_1798__Codevs_2216_[AHOI_2009]_行星序列_(线段树)
描述
BZOJ: http://www.lydsy.com/JudgeOnline/problem.php?id=1798
Codevs: http://codevs.cn/problem/2216/
给出n和行星的质量,进行m次操作:
1.将[l,r]区间内所有行星质量*c.
2.将[l,r]区间内所有行星质量+c.
3.询问[l,r]区间内行星质量和.
分析
双标记线段树,多加一个乘法的标记.a[k]位置的标记表示的是要传给a[k]的子节点的值,乘法位置为a[k].f,加法为a[k].p,表示的是先乘后加.按照先乘后加的规定,当跟新值时,ax+b变为(ax+b)*c1+c2=axc1+bc1+c2=(axc1)+(bc1+c2),也就是标记向下传递(push_down)的时候,乘法位置要乘,加法位置要先乘后加.
之前一直wa,最后才发现数组没开够...
感觉好像把乘法转化为加法也能做...但没尝试.
注意:
1.最好在确保扔给函数的参数都是取过模的,这样不容易出错.
2.可以不用long long定义,在乘法的时候强制转换一下就好了.
1 #include<cstdio> 2 #include<algorithm> 3 #define ll long long 4 #define lson 2*k 5 #define rson 2*k+1 6 7 const int maxn=1e5+5; 8 int n,m,mod; 9 int w[maxn]; 10 struct node { int l,r,x,f,p; }a[3*maxn]; 11 12 void build_tree(int l,int r,int k) 13 { 14 a[k].l=l; a[k].r=r; a[k].f=1; a[k].p=0; 15 if(l==r) 16 { 17 a[k].x=w[l]; 18 return; 19 } 20 int mid=l+(r-l)/2; 21 build_tree(l,mid,lson); 22 build_tree(mid+1,r,rson); 23 a[k].x=(a[lson].x+a[rson].x)%mod; 24 } 25 26 inline void cal(int k,int f,int p) 27 { 28 a[k].x=(int)((((ll)a[k].x*(ll)f)%mod+((ll)(a[k].r-a[k].l+1)%mod)*(ll)p)%mod); 29 a[k].f=(int)(((ll)a[k].f*(ll)f)%mod); 30 a[k].p=(int)((((ll)a[k].p*(ll)f)%mod+p)%mod); 31 } 32 33 inline void push_down(int k) 34 { 35 cal(lson,a[k].f,a[k].p); 36 cal(rson,a[k].f,a[k].p); 37 a[k].f=1; 38 a[k].p=0; 39 } 40 41 void update(int l,int r,int k,int f,int p) 42 { 43 if(a[k].l==l&&a[k].r==r) 44 { 45 cal(k,f,p); 46 return; 47 } 48 if(a[k].f!=1||a[k].p) 49 { 50 push_down(k); 51 } 52 int mid=a[k].l+(a[k].r-a[k].l)/2; 53 if(r<=mid) 54 { 55 update(l,r,lson,f,p); 56 } 57 else if(l>mid) 58 { 59 update(l,r,rson,f,p); 60 } 61 else 62 { 63 update(l,mid,lson,f,p); 64 update(mid+1,r,rson,f,p); 65 } 66 a[k].x=(a[lson].x+a[rson].x)%mod; 67 } 68 69 int search(int l,int r,int k) 70 { 71 if(a[k].l==l&&a[k].r==r) 72 { 73 return a[k].x; 74 } 75 if(a[k].f!=1||a[k].p) 76 { 77 push_down(k); 78 } 79 int mid=a[k].l+(a[k].r-a[k].l)/2; 80 if(r<=mid) 81 { 82 return (search(l,r,lson)%mod); 83 } 84 else if(l>mid) 85 { 86 return (search(l,r,rson)%mod); 87 } 88 else 89 { 90 return ((search(l,mid,lson)+search(mid+1,r,rson))%mod); 91 } 92 } 93 94 int main() 95 { 96 #ifndef ONLINE_JUDGE 97 freopen("star.in","r",stdin); 98 freopen("star.out","w",stdout); 99 #endif 100 scanf("%d%d",&n,&mod); 101 102 for(int i=1;i<=n;i++) 103 { 104 scanf("%d",&w[i]); 105 } 106 build_tree(1,n,1); 107 scanf("%d",&m); 108 int qry,l,r,c; 109 for(int i=1;i<=m;i++) 110 { 111 scanf("%d%d%d",&qry,&l,&r); 112 switch(qry) 113 { 114 case 1: 115 scanf("%d",&c); 116 c%=mod; 117 update(l,r,1,c,0); 118 break; 119 case 2: 120 scanf("%d",&c); 121 c%=mod; 122 update(l,r,1,1,c); 123 break; 124 case 3: 125 printf("%d\n",search(l,r,1)); 126 break; 127 } 128 } 129 #ifndef ONLINE_JUDGE 130 fclose(stdin); 131 fclose(stdout); 132 system("star.out"); 133 #endif 134 return 0; 135 }
View Code
转载于:https://www.cnblogs.com/Sunnie69/p/5436371.html
BZOJ_1798__Codevs_2216_[AHOI_2009]_行星序列_(线段树)相关推荐
- 【BZOJ-1858】序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1961 Solved: 991 [Submit][Stat ...
- BZOJ1858 [Scoi2010]序列操作 线段树
欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1858 题意概括 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1 ...
- Wannafly挑战赛22 D 整数序列 (线段树维护三角函数值)
链接:https://ac.nowcoder.com/acm/contest/160/D 来源:牛客网 整数序列 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语 ...
- HYSBZ - 1798 Seq 维护序列seq 线段树lazy标记
传送门 这道题属实是线段树的道比刷题,又加又乘的,当然还可能会有乘除,阶乘等等可能的情况. 对于这道题,主要的一个就是怎么记录lazy标记,首先的话一个数组是肯定不行的,设乘的为lazy,加的为add ...
- [HNOI2016] 序列(线段树 + 莫队 + 倍增)
problem luogu-P3246 心路历程+卡常历程+问题存疑 一直在想莫队的做法.发现左右指针的移动对应一段左/右端点固定的子序列,然后可以一个数代表一段相同的贡献. 就开始求 lsti,nx ...
- Wannafly挑战赛22 D-整数序列 (线段树)
https://www.nowcoder.com/acm/contest/160/D 做法:用线段树维护,对于树上的每个叶子结点,维护一个复数结构体 cos(a[i] + sin(a[i])*i ,每 ...
- Luogu P2572 [SCOI2010]序列操作 线段树。。
咕咕了...于是借鉴了小粉兔的做法ORZ... 其实就是维护最大子段和的线段树,但上面又多了一些操作....QWQ 维护8个信息:1/0的个数(sum),左/右边起1/0的最长长度(ls,rs),整段 ...
- Java_太阳系_行星模型_小游戏练习_详细注释
1 //实现MyFrame--实现绘制窗口,和实现重写 重画窗口线程类 2 3 package cn.xiaocangtian.Test; 4 5 import java.awt.Frame; 6 i ...
- bzoj 2962 序列操作 线段树
这个题卡常数.. 首先c比较小,所以可以考虑dp转移,对于合并子序列就直接枚举跨区间的就可以了 对于反转操作,要注意只有奇数位置才会变成相反数 对于增加操作,可以考虑抽象成组合数学问题: 对于(a1+ ...
最新文章
- c语言程序设计01,c语言程序设计01.doc
- php的引用变量与销毁机制
- IDEA 方法注释模板和类注释模板
- 制造业如何将工人师傅的隐性技能转化为显性知识?
- LV 旗下公司的识别算法: 4 秒鉴定假包,准确率达 99.1%
- 修正mysqlcc在MySQL 5.0上常报的 Table 'xxx' doesn't exist 错误
- ExtJS入门(08)窗口,按钮,输入框,
- 使用MAP文件快速定位程序崩溃代码行(转)
- [渝粤教育] 西南科技大学 微机原理与应用 在线考试复习资料(1)
- MySQL划重点-查询-条件
- JAVA之private修饰成员方法默认是final型的?
- 【TensorFlow】TensorFlow函数精讲之tf.nn.max_pool()和tf.nn.avg_pool()
- 新西兰计算机专业研究生一年,【新西兰计算机专业研究生】 - 教外新西兰留学网...
- 最好用的五大服装进销存管理软件,强推第一个
- 软件测试周刊(第37期):不能随便生气
- 第三章 心剑,有妹紫灵
- 安装infinity后主页始终显示百度页面?
- 魅族手机CUP浮点运算测试BUG
- 全系列毕业设计论文来了
- 英语六级口语 计算机,2020年5月英语六级口语惯用口语:计算机