HDU 5239 上海大都会 D题(线段树+数论)
2015-05-30 10:18
501 查看
打表,发现规律是存在一定次数(较小)后,会出现a=(a*a)%p。可以明显地发现本题与线段树有关。设置标记flag,记录本段内的数是否均已a=a*a%p。若是,则不需更新,否则更新有叶子结点,再pushup。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL unsigned long long using namespace std; const LL p=9223372034707292160uLL; const int N=100050; int n; LL seg[N<<2],s; bool flag[N<<2]; void build(int rt,int l,int r){ flag[rt]=false; if(l==r){ scanf("%llu",&seg[rt]); // cout<<l<<"="<<seg[rt]<<endl; return ; } int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r); seg[rt]=(seg[rt<<1]+seg[rt<<1|1])%p; } LL mul(LL a,LL b){ LL res=0; while(b){ if(b&1) res=(res+a)%p; b>>=1; a=(a+a)%p; } return res; } void update(int rt,int l,int r,int L,int R){ if(flag[rt]&&l<=L&&R<=r){ s=(s+seg[rt])%p; return ; } if(L==R){ s=(s+seg[rt])%p; LL tmp=mul(seg[rt],seg[rt]); if(seg[rt]==tmp){ flag[rt]=true; } seg[rt]=tmp; return ; } int m=(L+R)>>1; if(r<=m){ update(rt<<1,l,r,L,m); } else if(l>=m+1) update(rt<<1|1,l,r,m+1,R); else{ update(rt<<1,l,r,L,m); update(rt<<1|1,l,r,m+1,R); } flag[rt]=flag[rt<<1]&flag[rt<<1|1]; seg[rt]=(seg[rt<<1]+seg[rt<<1|1])%p; } int main(){ int T,icase=0,k,l,r; scanf("%d",&T); while(T--){ s=0; scanf("%d%d",&n,&k); build(1,1,n); printf("Case #%d:\n",++icase); for(int i=1;i<=k;i++){ scanf("%d%d",&l,&r); update(1,l,r,1,n); printf("%llu\n",s); } } return 0; }
相关文章推荐
- 阅读8.9.10章
- 2013斯坦福大学iOS应用开发学习笔记 11 Table View and iPad
- 与人说话
- poj1061青蛙的约会 扩展欧几里得
- 常用正则表达式
- 1.CentOS 6.5 静态网站制作学习
- ZOJ 3713 In 7-bit
- ASP.NET MVC中如何使用PartialView
- 一步一步教你实现CTreeCtrl 自绘
- mysql之group by,order by
- IE8~实现未知节点高度实现垂直居中
- 使用Dojo(一) widget的生命周期管理
- SSDT-BI之七:循环任务(容器)
- 闲谈MongoDb+GridFS+Nginx
- Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析
- 通过代码自定义cell
- 前端常用工具整理
- 接入微信SDK64位包报错
- 某著名公司2015暑期实习招聘试题及相关内容复习
- redhat 安装ceph