HDU4973:A simple simulation problem.(线段树)

Problem Description
There are n types of cells in the lab, numbered from 1 to n. These cells are put in a queue, the i-th cell belongs to type i. Each time I can use mitogen to double the cells in the interval [l, r]. For instance, the original queue is {1 2 3 3 4 5}, after using a mitogen in the interval [2, 5] the queue will be {1 2 2 3 3 3 3 4 4 5}. After some operations this queue could become very long, and I can’t figure out maximum count of cells of same type. Could you help me?
 

Input
The first line contains a single integer t (1 <= t <= 20), the number of test cases.

For each case, the first line contains 2 integers (1 <= n,m<= 50000) indicating the number of cell types and the number of operations.

For the following m lines, each line represents an operation. There are only two kinds of operations: Q and D. And the format is:

“Q l r”, query the maximum number of cells of same type in the interval [l, r];
“D l r”, double the cells in the interval [l, r];

(0 <= r – l <= 10^8, 1 <= l, r <= the number of all the cells)
 

Output
For each case, output the case number as shown. Then for each query "Q l r", print the maximum number of cells of same type in the interval [l, r].

Take the sample output for more details.
 

Sample Input
   
   
   
   
1 5 5 D 5 5 Q 5 6 D 2 3 D 1 2 Q 1 7
 

Sample Output
   
   
   
   
Case #1: 2 3
#include<stdio.h>
#define L 50005
#define ll __int64
#define ls 2*i
#define rs 2*i+1
#define w(x) while(x)
#define max(a,b) (a>b?a:b)
int t,n,m,cas=1;
ll x,y,ans,res;
char str[10];
struct node
{
    int l,r,flag;
    ll maxn,sum;
} a[L<<2];
void PushUp(int i)
{
    a[i].sum=a[2*i].sum+a[2*i+1].sum;
    a[i].maxn=max(a[2*i].maxn,a[2*i+1].maxn);
}
void PushDown(int i)
{
    if(a[i].flag)
    {
        a[ls].flag += a[i].flag;
        a[rs].flag += a[i].flag;
        w(a[i].flag--)
        {
            a[ls].maxn *= 2;
            a[rs].maxn *= 2;
            a[ls].sum *= 2;
            a[rs].sum *= 2;
        }
        a[i].flag=0;
    }
}
void init(int l,int r,int i)
{
    a[i].l=l;
    a[i].r=r;
    a[i].flag=0;
    a[i].maxn=1;
    if(l==r)
    {
        a[i].sum=1;
        return;
    }
    int mid=(l+r)/2;
    init(l,mid,ls);
    init(mid+1,r,rs);
    PushUp(i);
}
int find(int i,ll x,ll &k,ll &tem)
{
    if(a[i].l==a[i].r)
    {
        k=x;
        tem=a[i].sum;
        return a[i].l;
    }
    PushDown(i);
    if(x<=a[ls].sum) return find(ls,x,k,tem);
    else return find(rs,x-a[ls].sum,k,tem);
}
void insert1(int i,int p,ll v)
{
    if(a[i].l==a[i].r)
    {
        a[i].maxn+=v;
        a[i].sum+=v;
        return;
    }
    PushDown(i);
    int mid=(a[i].l+a[i].r)/2;
    if(p<=mid) insert1(ls,p,v);
    else insert1(rs,p,v);
    PushUp(i);
}
void insert2(int l,int r,int i)
{
    if(l<=a[i].l&&a[i].r<=r)
    {
        PushDown(i);
        a[i].flag++;
        a[i].sum*=2;
        a[i].maxn*=2;
        return;
    }
    PushDown(i);
    int mid=(a[i].l+a[i].r)/2;
    if(l<=mid) insert2(l,r,ls);
    if(r>mid) insert2(l,r,rs);
    PushUp(i);
}
void query(int l,int r,int i)
{
    if(l<=a[i].l&&a[i].r<=r)
    {
        res=max(res,a[i].maxn);
        return;
    }
    PushDown(i);
    int mid=(a[i].l+a[i].r)/2;
    if(l<=mid) query(l,r,ls);
    if(r>mid) query(l,r,rs);
}
int main()
{
    scanf("%d",&t);
    w(t--)
    {
        scanf("%d%d",&n,&m);
        init(1,n,1);
        printf("Case #%d:\n",cas++);
        w(m--)
        {
            scanf("%s%I64d%I64d",str,&x,&y);
            ll lk,rk,tem;
            int r=find(1,y,rk,tem);
            int l=find(1,x,lk,tem);
            if(str[0]=='D')
            {
                if(l==r)
                {
                    insert1(1,l,rk-lk+1);
                    continue;
                }
                insert1(1,r,rk);
                insert1(1,l,tem-lk+1);
                if(r-l>1)
                    insert2(l+1,r-1,1);
            }
            else
            {
                ans=0;
                if(l==r)
                {
                    printf("%I64d\n",rk-lk+1);
                    continue;
                }
                ans=max(ans,max(rk,tem-lk+1));
                if(r-l>1)
                {
                    res=0;
                    query(l+1,r-1,1);
                    ans=max(ans,res);
                }
                printf("%I64d\n",ans);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(线段树,HDU)