HDU4973A simple simulation problem.(线段树,区间更新)

A simple simulation problem.

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 330    Accepted Submission(s): 132

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

题意:D:在区间内的所有点个数都变成2倍,总区间变长,Q:询问区间内的同一个数最多出现的次数。

#include<stdio.h>
#define N 50005
#define ll __int64
struct nn
{
    ll sum,maxlen,mulit;//分别代表当前节点区间总个数,同一个数最多个数,子节点需更新的倍数
}tree[N*3];
void builde(ll l,ll r,int k)
{
    tree[k].sum=r-l+1;
    tree[k].maxlen=1; tree[k].mulit=1;
    if(l==r)return ;
    ll m=(l+r)/2;
    builde(l,m,k*2); builde(m+1,r,k*2+1);
}
ll MAX(ll a,ll b){return a>b?a:b;}
void setchilde(int k)
{
        tree[k*2].mulit*=tree[k].mulit;
        tree[k*2].sum*=tree[k].mulit;
        tree[k*2].maxlen*=tree[k].mulit;

        tree[k*2+1].mulit*=tree[k].mulit;
        tree[k*2+1].sum*=tree[k].mulit;
        tree[k*2+1].maxlen*=tree[k].mulit;

        tree[k].mulit=1;
}
void set(ll l,ll r,int k,ll L,ll R,ll suml)
{
    ll m=(l+r)/2;
    if(L<=suml+1&&suml+tree[k].sum<=R)
    {
        tree[k].maxlen*=2; tree[k].mulit*=2;  tree[k].sum*=2;
        return ;
    }
    else if(l==r)
    {
        if(tree[k].sum+suml>=R&&suml+1>=L)
            tree[k].sum=tree[k].sum+suml-R+(R-suml)*2;
        else if(tree[k].sum+suml>=R&&suml+1<=L)
            tree[k].sum=tree[k].sum+suml-R+L-suml-1+(R-L+1)*2;
        else if(tree[k].sum+suml<=R&&suml+1<=L)
            tree[k].sum=(tree[k].sum+suml-L+1)*2+L-suml-1;
        tree[k].maxlen=tree[k].sum;
            return ;
    }
    if(tree[k].mulit>1)
        setchilde(k);
    ll sum=tree[k*2].sum;
    if(suml+sum>=L)set(l,m,k*2,L,R,suml);
    if(suml+sum+1<=R)set(m+1,r,k*2+1,L,R,suml+sum);

    tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
    tree[k].maxlen=MAX(tree[k*2].maxlen,tree[k*2+1].maxlen);
}
ll query(ll l,ll r,int k,ll L,ll R,ll suml)
{
     ll m=(l+r)/2, maxlen;
    if(suml+1>=L&&tree[k].sum+suml<=R)
    {
        return tree[k].maxlen;
    }
    else if(l==r)
    {
       if(tree[k].sum+suml>=R&&suml+1>=L)
            maxlen=R-suml;
        else if(tree[k].sum+suml>=R&&suml+1<=L)
            maxlen=R-L+1;
        else if(tree[k].sum+suml<=R&&suml+1<=L)
            maxlen=tree[k].sum+suml-L+1;
            return maxlen;
    }
    if(tree[k].mulit>1)
        setchilde(k);
    if(tree[k*2].sum+suml>=R)
        maxlen=query(l,m,k*2,L,R,suml);
    else if(tree[k*2].sum+1+suml<=L)maxlen=query(m+1,r,k*2+1,L,R,tree[k*2].sum+suml);
    else maxlen= MAX(query(l,m,k*2,L,R,suml),query(m+1,r,k*2+1,L,R,tree[k*2].sum+suml));
    return maxlen;
}
int main()
{
    ll n,m,L,R,t,tt=0;
    char s[5];
    scanf("%I64d",&t);
    while(t--)
    {
        scanf("%I64d%I64d",&n,&m);
        builde(1,n,1);
        printf("Case #%I64d:\n",++tt);
        while(m--)
        {
            scanf("%s%I64d%I64d",s,&L,&R);
            if(s[0]=='D')set(1,n,1,L,R,0);
            else printf("%I64d\n",query(1,n,1,L,R,0));
        }
    }
}
时间: 2024-11-11 07:24:28

HDU4973A simple simulation problem.(线段树,区间更新)的相关文章

Light OJ 1080 - Binary Simulation - (线段树区间更新 单点查询)

Description Given a binary number, we are about to do some operations on the number. Two types of operations can be here. 'I i j'    which means invert the bit from i to j (inclusive) 'Q i'    answer whether the ith bit is 0 or 1 The MSB (most signif

hdu 4973 A simple simulation problem.(线段树)

http://acm.hdu.edu.cn/showproblem.php?pid=4973 有两种操作 D l r 将[l,r]区间翻倍 Q l r询问[l,r]中相同数字出现的最多次数 比赛的时候脑子太乱了,没有想到怎么做.发现每次翻倍序列的长度都在变化,区间对应的数也在变,没有思路. 但是静下心来想一想,思路还是挺清晰的. 无论怎么翻倍,序列中的数都是连续的,范围是1~n.可以拿一个数组来记录每个数出现的次数,当更新或询问区间[l,r]时,可以利用其前缀和找到区间[l,r]对应的数字分别是

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

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

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

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

PKU A Simple Problem with Integers (线段树区间更新求和)

题意:典型的线段树C,Q问题,有n个数a[i] (1~n),C, a, b,c在[a,b]区间增加c Q a b 求[a,b]的和. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath> #include<iostream> #include <queue> #i

poj 3468 A Simple Problem with Integers (线段树区间更新入门)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 70442   Accepted: 21723 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

POJ 3468 A Simple Problem with Integers(线段树 区间更新)

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In