HDU5239 Doom(线段树,区间更新,区间平方)

Problem Description

THE END IS COMINGGGGGG!

Mike has got stuck on a mystery machine. If he cannot solve this
problem, he will go to his doom.

This machine is consist of n cells, and a screen. The i-th cell
contains a number ai(1≤i≤n). The screen also contains a number s,
which is initially 0.

There is a button on each cell. When the i-th is pushed, Mike observes
that, the number on the screen will be changed to s+ai, where s is the
original number. and the number on the i-th cell will be changed to
a2i.

Mike observes that the number is stored in radix p, where
p=9223372034707292160. In other words , the operation is under modulo
p.

And now, Mike has got a list of operations. One operation is to push
buttons between from l-th to r-th (both included), and record the
number on the screen. He is tired of this stupid work, so he asks for
your help. Can you tell him, what are the numbers recorded.

Input

The first line contains an integer T(T≤5), denoting the number of test
cases.

For each test case, the first line contains two integers
n,m(1≤n,m≤105).

The next line contains n integers ai(0≤ai

Output

For each test case, output ”Case #t:”, to represent this is the t-th
case. And then output the answer for each query operation, one answer
in a line.

For more details you can take a look at the example.

Sample Input

2
4 4
2 3 4 5
1 2
2 3
3 4
1 4
1 3
2
1 1
1 1
1 1

Sample Output

Case #1:
5
18
39
405
Case #2:
2
6
22

思路

首先说题意,给了n个数,有m次询问,定义一个和为sum=0,每次询问一个区间[a,b]的和+sum,在输出这个区间的和之后,把这个区间的每个数变成自己的平方,然后对9223372034707292160这个数取模

因为模数太大,所以要在进行平方的时候用到快速乘法,用unsigned long long来进行输入输出,我们有一个规律,一个数一直平方,在平方到一定的次数以后,这个数对模数取模的值就不会改变了,所以我们用一个flag数组记录一下这个区间的值还改不改变,当flag=1时就代表已经不变了,就不用去更新了
提交选择G++

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
using namespace std;
typedef unsigned long long ll;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const ll N=1e5+20;
const ll mod=9223372034707292160ull;
ll sum[N<<2];
int flag[N<<2];
void pushup(ll rt)
{
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;
    flag[rt]=flag[rt<<1]&flag[rt<<1|1];
}
void build(ll l,ll r,ll rt)
{
    if(l==r)
    {
        scanf("%llu",&sum[rt]);
        flag[rt]=0;
        return;
    }
    ll m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
ll q_mul(ll a,ll b)
{
    ll ans=0;
    while(b)
    {
        if(b&1)
        {
            ans=(ans+a)%mod;
        }
        a=(a+a)%mod;
        b>>=1;
    }
    return ans;
}
void update(ll a,ll b,ll l,ll r,ll rt)
{
    if(flag[rt])return;
    if(l==r)
    {
        ll tmp=q_mul(sum[rt],sum[rt]);
        if(tmp==sum[rt])
            flag[rt]=1;
        sum[rt]=tmp;
        return;
    }
    ll m=(l+r)>>1;
    if(a<=m)
        update(a,b,lson);
    if(b>m)
        update(a,b,rson);
    pushup(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt)
{
    if(L<=l&&r<=R)
        return sum[rt];
    ll m=(l+r)>>1;
    ll ans=0;
    if(L<=m)
        ans=(ans+query(L,R,lson))%mod;
    if(R>m)
        ans=(ans+query(L,R,rson))%mod;
    return ans;
}
int main()
{
    ll t,n,m,q=1,x;
    scanf("%llu",&t);
    while(t--)
    {
        scanf("%llu%llu",&n,&m);
        build(1,n,1);
        ll sum=0,a,b;
        printf("Case #%llu:\n",q++);
        while(m--)
        {
            scanf("%llu%llu",&a,&b);
            sum=(sum+query(a,b,1,n,1))%mod;
            printf("%llu\n",sum);
            update(a,b,1,n,1);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值