HDU 5239 DOOM 线段树

HDU 5239 DOOM 线段树

标签(空格分隔): 线段树


题目链接:hdu5239
题意:给定长度为N的序列,有Q个操作,每次操作询问区间[l,r]的和,并将区间的值平方,每次输出所有之前查询答案的和对2^63-2^31取模。
思路:找规律发现任何数平方30次之后模mod都不再变化。于是用线段树维护区间内平方次数最少的元素为多少,弱最小的大于30则不进行操作,直接返回区间和,反之则继续递归直至叶子节点。
代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define Lson o<<1,l,mid
#define Rson o<<1|1,mid+1,r
const int maxn =100010;
int minv[maxn*4];
unsigned long long sum[maxn*4];
long long data[maxn];
const long long mod=((1ll<<63)-(1ll<<31));
void sqr(int i){
    long long tp1,tp2;
    tp1=tp2=sum[i];
    __asm__("movq %1,%%rax\n imulq %2\n idivq %3\n":"=d"(sum[i]):"m"(tp1),"m"(tp2),"m"(mod):"%rax");
}
unsigned long long modify(int o,int l,int r,int L,int R){
    if(minv[o]>31&&L<=l&&R>=r) return sum[o];
    unsigned long long ret=0;
    if(l==r){
        ret=sum[o];
        sqr(o);
        minv[o]++;
        return ret;
    }
    int mid=(l+r)>>1;
    if(L<=mid)ret=(ret+modify(Lson,L,R))%mod;
    if(R>mid) ret=(ret+modify(Rson,L,R))%mod;
    sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
    minv[o]=min(minv[o<<1],minv[o<<1|1]);
    return ret;
}
void init(int o,int l,int r){
    if(l==r){
        minv[o]=0;
        sum[o]=data[l];
        return ;
    }
    int mid=(l+r)>>1;
    init(Lson);init(Rson);
    sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
    minv[o]=0;
}
int main(){
    int T,cas=0;
//    freopen("data.in","r",stdin);
    scanf("%d",&T);
    while(T--){
        memset(sum,0,sizeof(sum));
        printf("Case #%d:\n",++cas);
        int n,q,l,r;
        unsigned long long ans=0;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)scanf("%I64d",data+i);
        init(1,1,n);
        while(q--){
            scanf("%d%d",&l,&r);
            ans=(ans+modify(1,1,n,l,r))%mod;
            printf("%I64d\n",(long long)ans);
        }
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值