首页 > 代码库 > HDU-4937-A simple simulation problem.(线段树)

HDU-4937-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
 

Source
2014 Multi-University Training Contest 10
 

思路:每次操作和查询前找区间端点对应的位置,分情况处理。

#include <stdio.h>
#define max(A,B)(A>B?A:B)

long long sum[200005],att[200005],mx[200005],remain;

void build(int idx,int s,int e)
{
    if(s!=e)
    {
        int mid=(s+e)>>1;

        build(idx<<1,s,mid);
        build(idx<<1|1,mid+1,e);

        sum[idx]=sum[idx<<1]+sum[idx<<1|1];
    }
    else sum[idx]=1;

    att[idx]=0;
    mx[idx]=1;
}

void segupdate(int idx,int s,int e,int l,int r)
{
    if(s==l && r==e)
    {
        sum[idx]*=2;
        mx[idx]*=2;

        att[idx]++;

        return;
    }

    int mid=(s+e)>>1;

    if(att[idx])
    {
        sum[idx<<1]<<=att[idx];
        sum[idx<<1|1]<<=att[idx];

        mx[idx<<1]<<=att[idx];
        mx[idx<<1|1]<<=att[idx];

        att[idx<<1]+=att[idx];
        att[idx<<1|1]+=att[idx];

        att[idx]=0;
    }

    if(r<=mid) segupdate(idx<<1,s,mid,l,r);
    else if(l>mid) segupdate(idx<<1|1,mid+1,e,l,r);
    else
    {
        segupdate(idx<<1,s,mid,l,mid);
        segupdate(idx<<1|1,mid+1,e,mid+1,r);
    }

    sum[idx]=sum[idx<<1]+sum[idx<<1|1];
    mx[idx]=max(mx[idx<<1],mx[idx<<1|1]);
}

void update(int idx,int s,int e,int pos,int val)
{
    if(s==e)
    {
        sum[idx]+=val;
        mx[idx]+=val;

        return;
    }

    if(att[idx])
    {
        sum[idx<<1]<<=att[idx];
        sum[idx<<1|1]<<=att[idx];

        mx[idx<<1]<<=att[idx];
        mx[idx<<1|1]<<=att[idx];

        att[idx<<1]+=att[idx];
        att[idx<<1|1]+=att[idx];

        att[idx]=0;
    }

    int mid=(s+e)>>1;

    if(pos<=mid) update(idx<<1,s,mid,pos,val);
    else update(idx<<1|1,mid+1,e,pos,val);

    sum[idx]=sum[idx<<1]+sum[idx<<1|1];
    mx[idx]=max(mx[idx<<1],mx[idx<<1|1]);
}

int query(int idx,int s,int e,long long val,bool flag)
{
    if(s==e)
    {
        if(flag) remain=sum[idx]-val+1;
        else remain=val;

        return s;
    }

    if(att[idx])
    {
        sum[idx<<1]<<=att[idx];
        sum[idx<<1|1]<<=att[idx];

        mx[idx<<1]<<=att[idx];
        mx[idx<<1|1]<<=att[idx];

        att[idx<<1]+=att[idx];
        att[idx<<1|1]+=att[idx];

        att[idx]=0;
    }

    int mid=(s+e)>>1;

    if(val<=sum[idx<<1]) return query(idx<<1,s,mid,val,flag);
    else return query(idx<<1|1,mid+1,e,val-sum[idx<<1],flag);
}

long long querymax(int idx,int s,int e,int l,int r)
{
    if(s==l && e==r) return mx[idx];

    if(att[idx])
    {
        sum[idx<<1]<<=att[idx];
        sum[idx<<1|1]<<=att[idx];

        mx[idx<<1]<<=att[idx];
        mx[idx<<1|1]<<=att[idx];

        att[idx<<1]+=att[idx];
        att[idx<<1|1]+=att[idx];

        att[idx]=0;
    }

    int mid=(s+e)>>1;

    if(r<=mid) return querymax(idx<<1,s,mid,l,r);
    else if(l>mid) return querymax(idx<<1|1,mid+1,e,l,r);
    else
    {
        long long tempa=querymax(idx<<1,s,mid,l,mid);
        long long tempb=querymax(idx<<1|1,mid+1,e,mid+1,r);

        return max(tempa,tempb);
    }
}

int main()
{
    int T,n,m,l,r,cases=1;
    long long a,b,ar,br,ans;
    char s[5];

    scanf("%d",&T);

    while(T--)
    {
        scanf("%d%d",&n,&m);

        printf("Case #%d:\n",cases++);

        build(1,1,n);

        while(m--)
        {
            scanf("%s%I64d%I64d",s,&a,&b);

            if(s[0]=='D')
            {
                l=query(1,1,n,a,1);
                ar=remain;
                r=query(1,1,n,b,0);
                br=remain;

                if(l==r) update(1,1,n,l,b-a+1);
                else
                {
                    update(1,1,n,l,ar);
                    update(1,1,n,r,br);

                    if(l+1<=r-1) segupdate(1,1,n,l+1,r-1);
                }
            }
            else
            {
                l=query(1,1,n,a,1);
                ar=remain;
                r=query(1,1,n,b,0);
                br=remain;

                if(l==r) printf("%I64d\n",b-a+1);
                else
                {
                    ans=max(ar,br);

                    if(l+1<=r-1) ans=max(ans,querymax(1,1,n,l+1,r-1));

                    printf("%I64d\n",ans);
                }
            }
        }
    }
}


HDU-4937-A simple simulation problem.(线段树)