hdu 4578 线段树多重操作
来源:互联网 发布:巡更棒作弊软件 编辑:程序博客网 时间:2024/05/22 00:07
这道题一看题意很简单,一颗裸线段树,看似水题却不水,因为有很多细节问题得注意,如果没处理好就会各种TLE。
题意:四种操作,(1)op==1 [l,r]之间的所有数都增加一个数d.
(2) op==2 [l,r]之间的所有数都乘上一个数d.
(3) op==3 [l,r]之间的所有数都变为一个数d
(4) op==4 [l,r]计算 所有数的d次方的和
<span style="font-family: Arial, Helvetica, sans-serif;">思路: 可以用三种标记 三种操作,每次更新都不要更新到底,稍微标记一下即可。。。我第一次写的时候是三个操作三组函数,然后TLE。</span>
<span style="font-family: Arial, Helvetica, sans-serif;">昨天晚上学会了一种方法 就是只用一个变量标记即可(num),当num==-1表示 这个区间的数不一定相等,当num!=-1表示区间内的所有数都相同。</span>
<span style="font-family: Arial, Helvetica, sans-serif;">而且还得注意该取模的地方尽量都取模~</span>
<pre name="code" class="cpp">#include <iostream>#include <stdio.h>#include <cmath>#include <string.h>const int MAX=101000;const int mod=10007;using namespace std;struct node{ int l,r,num;}st[MAX*4]; void build(int v,int l,int r){ st[v].l=l; st[v].r=r; st[v].num=0; if(l==r)return; int mid=(l+r)/2; build(2*v,l,mid); build(2*v+1,mid+1,r);} int pow(int a,int b){ int ans=1; for(int i=1;i<=b;i++) ans=ans*a%mod; return ans%mod;} void updata(int v,int op,int l,int r,int p){ if(l<=st[v].l&&st[v].r<=r&&(st[v].num!=-1||op==3)) //如果把op==3去掉,TLE { if(op==3) //只要op==3,不管num是多少,直接覆盖,也就是op==3的优先级最高,对应与相应的区间 { st[v].num=p; } else if(op==2) { st[v].num=st[v].num*p%mod; } else if(op==1) { st[v].num=(st[v].num+p)%mod; } return; } if(st[v].num!=-1) //这里相当于pushdown(),就是要改变当前区间的子区间时,将当前区间的属性给左右孩子 { st[v*2].num=st[v].num; st[v*2+1].num=st[v].num; st[v].num=-1; } int mid=(st[v].l+st[v].r)/2; if(r<=mid)updata(2*v,op,l,r,p); else if(l>mid)updata(2*v+1,op,l,r,p); else { updata(2*v,op,l,mid,p); updata(2*v+1,op,mid+1,r,p); }} int getsum(int v,int l,int r,int p){ if(l<=st[v].l&&st[v].r<=r&&st[v].num!=-1) { return (r-l+1)*pow(st[v].num,p)%mod; } if(st[v].num!=-1) { st[v*2].num=st[v].num; st[v*2+1].num=st[v].num; st[v].num=-1; } int mid=(st[v].l+st[v].r)/2; if(r<=mid)return getsum(2*v,l,r,p); else if(l>mid)return getsum(2*v+1,l,r,p); else return (getsum(2*v,l,mid,p)+getsum(2*v+1,mid+1,r,p))%mod;}int main(){ int n,m; int op,x,y,p; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0)break; build(1,1,n); for(int i=0;i<m;i++) { scanf("%d%d%d%d",&op,&x,&y,&p); if(op==4) printf("%d\n",getsum(1,x,y,p)); else updata(1,op,x,y,p); } } return 0;}
0 0
- hdu 4578 线段树多重操作
- hdu-4578(线段树操作)
- HDU 4578 线段树 多lazy操作
- HDU 4578 线段树的四种操作
- hdu 4578 Transformation(线段树+多种操作)
- HDU 3954 线段树 特殊LAZY操作
- hdu 3333 线段树离线操作
- hdu 4630 线段树+在线操作
- hdu 2871 线段树(各种操作)
- hdu 3436 线段树 一顿操作
- hdu 3577 线段树区间操作(带有懒操作)
- hdu 4578 区间线段树
- hdu 4578 Transformation 线段树
- Hdu 4578 (线段树)
- HDU 4578 Transformation (线段树)
- hdu-4578-Transformation-线段树
- HDU 4578 Transformation 线段树
- hdu 4578 线段树模板
- ActiveMQ学习教程
- C# --习题笔记01
- servet
- 学习HEVC(1)
- python右键不显示IDLE
- hdu 4578 线段树多重操作
- 数据结构学习笔记之递归的应用
- 王景佳:基于Intel架构的SDN网络
- UITableView相关错误
- 内置函数--inline
- 对对话框的控件绘图
- C++中string类的常用函数
- Android--通知之Notification
- Farpoint 小总结