HDU ACM 4578 Transformation->线段树-区间修改
来源:互联网 发布:淘宝代收货款会计分录 编辑:程序博客网 时间:2024/05/17 05:14
分析:复杂的线段树操作。只有一个询问操作,就是询问[l,r]之间数的p次方之和,不可能全部查询所有的节点,会TLE,最好就是查询一段[a,b],这段区间所有的值都相等,即可以返回(b-a+1)*val 的值。根据询问操作可知要维护的是区间内所有值都相同的情况的区间。对于置初值和加乘操作,分两种情况:1、当为置初值操作,直接覆盖区间即可,并把标记的加乘操作赋为初始值。2、当为加乘操作时,先判断当前区间段是否为相同的值,是的话直接加乘,维护这个相同的值即可。如果不相同,看区间是否已有加乘标记,把这个加乘标记一直传递下去,直到遇见那个区间段区间所有值相同时停止。最后把这个加乘赋给最开始的区间段。简单的说就是,覆盖操作可直接维护,不是覆盖操作的话,区间只能保留一个加乘操作。
#include<iostream>using namespace std;#define lz t<<1,l,mid //左区间#define rz (t<<1)|1,mid+1,r //右区间#define N 100005#define MOD 10007__int64 add[N<<2],mul[N<<2],chan[N<<2],sum[N<<2];void Build(int t,int l,int r) //建立线段树{int mid;mul[t]=1;add[t]=sum[t]=0;chan[t]=0;if(l==r){chan[t]=1; //叶节点设为1,方便询问的查询return ;}mid=(l+r)>>1;Build(lz);Build(rz);}void PushDown(int t,int l,int r) //标记下传{int mid;if(l==r) return ;mid=(l+r)>>1;if(chan[t]) //set标记下传{add[t<<1]=0,mul[t<<1]=1;add[(t<<1)|1]=0,mul[(t<<1)|1]=1;chan[t<<1]=chan[(t<<1)|1]=1;sum[t<<1]=sum[(t<<1)|1]=sum[t];chan[t]=0;}else {if(add[t]) //加标记下传{ if(chan[t<<1]) sum[t<<1]=(sum[t<<1]+add[t])%MOD; //左子树有set标记 else{ PushDown(lz); //下传 add[t<<1]=(add[t<<1]+add[t])%MOD;} if(chan[(t<<1)|1]) sum[(t<<1)|1]=(sum[(t<<1)|1]+add[t])%MOD; //左子树有set标记 else{ PushDown(rz); //下传 add[(t<<1)|1]=(add[(t<<1)|1]+add[t])%MOD;} add[t]=0;}if(mul[t]>1) //乘标记下传{ if(chan[t<<1]) sum[t<<1]=(sum[t<<1]*mul[t])%MOD; //左子树有set标记 else{ PushDown(lz); //下传 mul[t<<1]=(mul[t<<1]*mul[t])%MOD;} if(chan[(t<<1)|1]) sum[(t<<1)|1]=(sum[(t<<1)|1]*mul[t])%MOD; //左子树有set标记 else{ PushDown(rz); //下传 mul[(t<<1)|1]=(mul[(t<<1)|1]*mul[t])%MOD;} mul[t]=1;}}}void Update(int t,int l,int r,int ul,int ur,int c,int op){int mid;if(l>=ul && ur>=r) //边界{if(op==3)chan[t]=1,mul[t]=1,add[t]=0,sum[t]=c;else if(chan[t]){if(op==1) sum[t]=(sum[t]+c)%MOD;else sum[t]=(sum[t]*c)%MOD;}else{PushDown(t,l,r); //下传if(op==1) add[t]=(add[t]+c)%MOD;else mul[t]=(mul[t]*c)%MOD;}return ;}PushDown(t,l,r);mid=(l+r)>>1;if(ur<=mid) Update(lz,ul,ur,c,op);else if(ul>mid) Update(rz,ul,ur,c,op);else{Update(lz,ul,mid,c,op);Update(rz,mid+1,ur,c,op);}}__int64 Query(int t,int l,int r,int ul,int ur,int p){int mid,i;__int64 ans,tp,t1,t2;if(ul<=l && r<=ur)if(chan[t]){ans=1;tp=sum[t];for(i=1;i<=p;i++) ans=(ans*tp)%MOD;return (r-l+1)*ans%MOD; //因为区间的每个部分都是相同的}PushDown(t,l,r); //下传标记mid=(l+r)>>1;if(ur<=mid) return Query(lz,ul,ur,p);else if(ul>mid) return Query(rz,ul,ur,p);else{t1=Query(lz,ul,mid,p);t2=Query(rz,mid+1,ur,p);return (t1+t2)%MOD;}}int main(){int n,m,i,l,r,c,op;while(scanf("%d%d",&n,&m)==2 && n+m){Build(1,1,n); //1为根节点for(i=1;i<=m;i++){scanf("%d%d%d%d",&op,&l,&r,&c);if(op<=3) Update(1,1,n,l,r,c,op);elseprintf("%I64d\n",Query(1,1,n,l,r,c)%MOD);}}return 0;}
0 0
- HDU ACM 4578 Transformation->线段树-区间修改
- HDU - 4578 Transformation(线段树 区间修改)
- hdu 4578 Transformation(区间线段树)
- hdu 4578 Transformation [线段树 区间更新]
- hdu 4578 Transformation(线段树维护区间次方和)
- hdu 4578 Transformation(线段树中级,区间和加强)
- hdu 4578 Transformation(线段树区间更新)
- HDU ACM 1698 Just a Hook->线段树+区间修改
- hdu 4578 Transformation 线段树
- HDU 4578 Transformation (线段树)
- hdu-4578-Transformation-线段树
- HDU 4578 Transformation 线段树
- HDU 4578 Transformation[线段树]
- hdu 4578 Transformation (线段树)
- hdu 4578 Transformation 线段树
- hdu 4578 Transformation 线段树
- HDU 4578 Transformation 线段树
- hdoj 4578 Transformation 【线段树 区间加、乘、修改、幂次求和】
- type alignment
- office 2007 卸载
- Android 启动Service监听网络状态
- Timer定时器、TimerTask、Random随机数
- JavaScript开发规范
- HDU ACM 4578 Transformation->线段树-区间修改
- Android开发好用的字符串处理工具
- webrtc callclient流程
- android 文件读取(assets、raw)
- Python 第三方 http 库-Requests 学习
- 本人在安装ADT Bundle for windows的各种问题总结
- 图形处理(五)基于旋转不变量的网格变形-Siggraph 2007
- 多线程编程 c++ /thread(detach,join)/ _beginthreadex
- Linux-常用命令(2)权限管理命令