hdu5239 Doom(线段树单点更新区间查询+数论)
2015-10-07 20:09
411 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5239
思路:
这题的mod是个很特殊的数。。对于任何数,连续乘以29次以上,取模就不再变化了。
这样题目就好做了,我只要通过区间查询,看当前区间里面的数中最小连乘次数是否超过29,如果超过29,就不再对点进行更新。
注意:由于mod很大,所以我两个数(mod-1)+(mod-1)时会爆long long ,所以可以采用快速乘法,然后用unsigned long long 即可。
代码:
http://acm.hdu.edu.cn/showproblem.php?pid=5239
思路:
这题的mod是个很特殊的数。。对于任何数,连续乘以29次以上,取模就不再变化了。
这样题目就好做了,我只要通过区间查询,看当前区间里面的数中最小连乘次数是否超过29,如果超过29,就不再对点进行更新。
注意:由于mod很大,所以我两个数(mod-1)+(mod-1)时会爆long long ,所以可以采用快速乘法,然后用unsigned long long 即可。
代码:
#include<stdio.h> #include<string.h> #define mod 9223372034707292160 #define M 100005 #define ll unsigned __int64 struct node { ll l,r,sum,cnt; }tree[M<<2]; ll a[M]; ll min(ll a,ll b){ return a<b?a:b; } ll quick( ll a,ll b) { ll ans=0; while(b) { if(b%2){ ans=ans+a; if(ans>=mod)ans=ans-mod; } a=(a+a); if(a>=mod) a=a-mod; b=b/2; } return ans; } void pushup(int root) { if(tree[root].l==tree[root].r)return; tree[root].sum=(tree[root<<1].sum%mod+tree[root<<1|1].sum%mod)%mod; tree[root].cnt=min(tree[root<<1].cnt,tree[root<<1|1].cnt); } void build(ll l,ll r, ll root) { tree[root].l=l; tree[root].r=r; tree[root].sum=0; tree[root].cnt=0; if(l==r){ tree[root].sum=a[l]; return; } ll mid=l+r>>1; build(l,mid,root<<1); build(mid+1,r,root<<1|1); pushup(root); } void update(ll l,ll r, ll root,ll z) { if(tree[root].cnt>29)return; if(tree[root].l==tree[root].r) { tree[root].sum=quick(tree[root].sum,tree[root].sum); tree[root].sum=tree[root].sum%mod; tree[root].cnt++; return; } ll mid=tree[root].l+tree[root].r>>1; if(r<=mid)update(l,r,root<<1,z); else if(l>mid)update(l,r,root<<1|1,z); else { update(l,mid,root<<1,z); update(mid+1,r,root<<1|1,z); } pushup(root); } ll query(ll l,ll r,ll root) { if(l==tree[root].l&&r==tree[root].r) { return tree[root].sum%mod; } ll mid=tree[root].l+tree[root].r>>1; if(r<=mid)return query(l,r,root<<1)%mod; else if(l>mid)return query(l,r,root<<1|1)%mod; else return (query(l,mid,root<<1)%mod+query(mid+1,r,root<<1|1)%mod)%mod; } int main() { int T,i,j,k,icase=0; ll n,m,left,right; scanf("%d",&T); while(T--) { icase++; scanf("%I64u%I64u",&n,&m); for(i=1;i<=n;i++) {scanf("%I64u",&a[i]); } build(1,n,1); ll ans=0; printf("Case #%d:\n",icase); while(m--) { scanf("%I64u%I64u",&left,&right); ans=ans+query(left,right,1); ans=ans%mod; printf("%I64u\n",ans%mod); update(left,right,1,-1); } } return 0; }
相关文章推荐
- ajax的使用方法
- input子系统分析一
- 项目34.1 分数的累加
- java web判断是否登录
- 数据库学习之范式理解
- NOIP2013 积木大赛
- JavaScript正则表达式验证身份证号码(From Jeskitt)
- 自己关于java编程的部分知识点总结
- 数学之美番外篇:平凡而又神奇的贝叶斯方法
- hdu 5015 233 Matrix
- Android4.2之Camera系统HAL调用流程
- 图像放缩中最近邻插值和双线性插值的基本原理
- keepalived + mysql主从
- 课堂2
- 【转】HTML5 基础知识,第 4 部分: 最后的完善
- 【Machine Learning in Action --4】朴素贝叶斯电子邮件垃圾过滤
- NOIP2013 货车运输
- 关于ASP.NET MVC的Html.BeginForm()方法
- SpriteBuilder给节点添加effect在32设备上发生crash
- POJ 2286 搜索 (IDA*)