您的位置:首页 > 其它

HDU5239 Doom

2016-05-01 14:32 337 查看
最后的结果忘记取模 WA到要哭。。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5239
这个是典型的线段树区间替换题目。
注意的是mod太大,会爆unsigned long long,需要用模乘法。
还有就是一个数取mod到一定次数会开始重复。(当A*A%mod==A)时就开始重复
用个数组v去判断。如果开始重复就v[...]=1;
然后如果两个子节点都开始重复不变了,那么父节点也是会开始重复不变。
AC代码如下:
#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#define lson o<<1,l,m#define rson (o<<1)|1,m+1,r#define maxn 1000005#define ll unsigned long long#define U unsignedconst ll mod=9223372034707292160Ull;using namespace std;ll sumv[maxn<<1],a[maxn];int v[maxn];ll multi_mod(ll a,ll b)//模乘法{ll ans=0;while(b){if(b&1) ans=ans+a;if(ans>=mod) ans-=mod;a<<=1;if(a>=mod) a-=mod;b>>=1;}return ans;}void build(int o,int l,int r){v[o]=0;if(l==r)return;int m=(r+l)>>1;build(lson);build(rson);}ll update(int o,int l,int r,int ql,int qr){if(v[o]&&ql<=l&&r<=qr)//区间覆盖且该区间不变了则返回值{return sumv[o];}ll ans=0;if(l==r)//叶节点要更改值{ans=a[l];a[l]=multi_mod(a[l],a[l]);if(a[l]==ans)//判断叶节点的值是否开始重复不变了{sumv[o]=ans;v[o]=1;}return ans;}int m=(l+r)>>1;if(ql<=m)ans+=update(lson,ql,qr);if(qr>m)ans+=update(rson,ql,qr);if(ans>=mod)ans-=mod;if(v[o<<1]&&v[(o<<1)|1])//左右区间不变 父节点也不变{sumv[o]=sumv[o<<1]+sumv[(o<<1)|1];if(sumv[o]>=mod)sumv[o]-=mod;v[o]=1;}return ans;}int main(){int n,m,T;scanf("%d",&T);for(int t=1;t<=T;t++){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%llu",&a[i]);build(1,1,n);ll ans=0;printf("Case #%d:\n",t);while(m--){int a,b;scanf("%d%d",&a,&b);ans+=update(1 , 1 , n , a , b );if(ans>=mod) ans-=mod;printf("%llu\n",ans);}}return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: