hdu5239Doom 线段树+找规律

//给出n个数据 , 对于每次[l,r]
//操作,s加上[l,r]区间的所有数
//之和,并且将[l,r]区间的所有数
//都平方
//输出s%9223372034707292160 
//打表可以发现对于每个数在做一定操作
//后其值一定不变
//所以只需要维护一个标记就行
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 1e5+10 ;
typedef unsigned long long ll ;
const ll mod = 9223372034707292160 ;
#define left v<<1
#define right v<<1|1
struct node
{
    int l , r ;
    ll  v ;
    int cnt ;
}tree[maxn<<2] ;
ll mul(ll a , ll b)
{
    ll c = 0 ;
    while(b)
    {
        if(b&1)
        {
            c+= a ;
            if(c >= mod)c-=mod ;
        }
        a += a ;
        if(a >= mod)a-=mod ;
        b >>= 1 ;
    }
    return c ;
}
void push_up(int v)
{
    tree[v].v = tree[left].v + tree[right].v ;
    if(tree[v].v >= mod)tree[v].v -= mod ;
    if(tree[left].cnt && tree[right].cnt)
    tree[v].cnt = 1 ; 
}
void build(int l , int r , int v)
{
    tree[v].l = l ;
    tree[v].r = r ;
    tree[v].cnt = 0 ;
    if(l == r)
    {
        scanf("%I64u" , &tree[v].v) ;
        if(tree[v].v >= mod)tree[v].v -= mod ;
        return  ;
    }
    int mid = (l + r) >> 1 ;
    build(l , mid , left) ;
    build(mid+1 , r , right) ;
    push_up(v) ;
}
ll update(int l , int r , int v)
{
    if(l <= tree[v].l && tree[v].r <= r)
        if(tree[v].cnt)
        return tree[v].v ;
    if(tree[v].l == tree[v].r)
    {
        ll tmp = tree[v].v ;
        tree[v].v = mul(tmp , tmp) ;
        if(tree[v].v == mul(tree[v].v , tree[v].v))
        tree[v].cnt = 1;
        return tmp ;
    }
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    ll ans = 0 ;
    if(l <= mid){
        ans+=update(l , r , left) ;
        if(ans >= mod)ans-=mod ;
    }
    if(r > mid){
        ans+= update(l , r , right) ;
        if(ans >= mod)ans-=mod ;
    }
    push_up(v) ;
    return ans ;
}
int main()
{
    int t ;
    scanf("%d" ,&t) ;
    int cas = 0 ;
    while(t--)
    {
        int n , m ;
        scanf("%d%d" ,&n , &m) ;
        build(1 , n , 1) ;
        ll s = 0 ;
        printf("Case #%d:\n" , ++cas) ;
        while(m--)
        {
            int l , r ;
            scanf("%d%d"  , &l , &r) ;
            s += update(l , r , 1) ;
            if(s >= mod)s-=mod ;
            printf("%I64u\n" , s) ;
        }
    }
    return  0 ;
}




































































你可能感兴趣的:(hdu5239Doom 线段树+找规律)