hdu4973A simple simulation problem. セグメントツリー

3639 ワード

//n(n<=5e4+10) , 1
//m(m<=5e4+10) 
//D l r  l,r 
//D l r  l,r 
// ,ss( ),ma( )
//mm( 2 )
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std  ;
const int maxn = 5e4+10 ;
#define left v<<1
#define right v<<1|1
typedef long long ll ;
struct Tree
{
    int l , r ;
    int mm;
    ll ss ;
    ll ma ;
}tree[maxn<<2] ;
void push_up(int v)
{
    tree[v].ma = max(tree[left].ma , tree[right].ma) ;
    tree[v].ss = tree[left].ss + tree[right].ss ;
}
void push_down(int v)
{
    if(tree[v].mm){
        ll tmp = ((ll)1)<<tree[v].mm ;
        tree[left].ss *= tmp ;
        tree[left].ma *= tmp ;
        tree[left].mm += tree[v].mm ;
        tree[right].ss *= tmp ;
        tree[right].ma *= tmp ;
        tree[right].mm += tree[v].mm ;
        tree[v].mm = 0 ;
    }
}
void build(int l , int r , int v)
{
    tree[v].l = l ;
    tree[v].r = r;
    tree[v].mm = 0 ;
    if(l == r){
        tree[v].ma = tree[v].ss = 1;
        return ;
    }
    int mid = (l + r) >> 1 ;
    build(l , mid , left) ;
    build(mid+1,r,right) ;
    push_up(v)  ;
}
void update(int l , int r , int v)
{
    if(l <= tree[v].l && tree[v].r <= r){
         tree[v].ss *= 2 ;
         tree[v].ma *= 2 ;
         tree[v].mm++;
         return  ;
    }
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    if(l <= mid)update(l,r,left) ;
    if(r > mid)update(l,r,right) ;
    push_up(v) ;
}
struct node
{
    ll pp ,ss , xx ;
};
node query(ll x , int v)
{
    if(tree[v].l == tree[v].r)
         return node{tree[v].l , tree[v].ss , x} ;
     push_down(v) ;
     node ans ;
     if(tree[left].ss >= x)
         ans = query(x , left) ;
     else ans = query(x-tree[left].ss , right) ;
     push_up(v) ;
     return ans ;
}
void add(int pos , ll x , int v)
{
    if(tree[v].l == tree[v].r){
        tree[v].ma += x ;
        tree[v].ss += x ;
        return ;
    }
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    if(pos <= mid)add(pos , x , left) ;
    else add(pos , x , right) ;
    push_up(v) ;
}
ll get_ans(int l , int r , int v)
{
    if(l <= tree[v].l && tree[v].r <= r)
        return tree[v].ma ;
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    ll ans = 0 ;
    if(l <= mid)ans = max(ans , get_ans(l,r,left)) ;
    if(r > mid) ans = max(ans , get_ans(l,r,right)) ;
    push_up(v) ;
    return ans  ;
}
int main()
{
    int t ;
    int cas = 0 ;
    scanf("%d" , &t) ;
    while(t--)
    {
        int n , m ;
        scanf("%d%d" , &n , &m) ;
        build(1,n,1) ;
        char ch[5] ;
        ll l , r ;
        printf("Case #%d:
" , ++cas) ; while(m--) { scanf("%s%lld%lld" , ch , &l , &r) ; node p1 = query(l,1) ; node p2 = query(r,1) ; if(ch[0] == 'D'){ if(p1.pp == p2.pp) add(p1.pp,r-l+1,1) ; else{ add(p1.pp,p1.ss-p1.xx+1,1) ; add(p2.pp,p2.xx,1) ; update(p1.pp+1,p2.pp-1,1) ; } } else { if(p1.pp == p2.pp) printf("%lld
" , r-l+1) ; else{ ll ans = max(p1.ss-p1.xx+1,p2.xx) ; ans = max(ans , get_ans(p1.pp+1,p2.pp-1,1)) ; printf("%lld
" , ans) ; } } } } return 0 ; }