[sicily]1686. Happy Children's Day

1686. Happy Children's Day

Constraints

Time Limit: 5 secs, Memory Limit: 32 MB

Description

Children's Day is coming. In this day, children will get a lot of candies. In MAX city, people develop an automatic candy management (ACM) system. ACM can manage N piles of candies. The system can carry out two operations.

1).I a b c (1<=a<=b<=N, 0<c<=100), ACM will add each pile numbered from a to b with c candies.  

2).C a b (1<=a<=b<=N), ACM will choose the pile (from a to b) with the most candies, and give all the candies in that pile to one child. If two or more piles have the most candies, then the pile with smaller id will be chosen.  

Given a series of instructions, for each operation C a b, please help the people to find out the number of candies a child can get.  

Input

Input may contain several test data sets.  

For each data set, the first line contains two integers N, M(0<N,M<=10^5) where N indicates the number of piles, and M indicates the number of operations that follows.  

Each of the next M lines describes one operation.  

Input will be ended by N=0,M=0,which should not be processed. 

NOTE: At the beginning of each data set, all of the N piles have 0 candies. 

Output

For each operation C a b, print the number of candies the child can get in a line. 

Sample Input

5 4I 1 5 1C 2 3I 2 2 4C 2 30 0

Sample Output

14
 
 
线段树,区间更新,采用延迟标记法。关于线段树,参考: http://www.cnblogs.com/TenosDoIt/p/3453089.html#b
#include <iostream>
#include <cstdio>
using namespace std;

const int MAX = 100001; 

struct Node
{
    int left, right;
    int max, index;
    int add;
}treeNode[4*MAX];

void build(int left, int right, int root) //初始化线段树
{
    treeNode[root].left = left;
    treeNode[root].right = right;
    treeNode[root].max = 0;
    treeNode[root].index = left;
    treeNode[root].add = 0;
    if(left==right)
        return;
    int mid = (left+right)>>1;
    build(left, mid, root<<1);
    build(mid+1, right, root<<1|1);
} 

void lazy(int root)		</span>//延迟标记更新
{
    treeNode[root<<1].add += treeNode[root].add;
    treeNode[root<<1].max += treeNode[root].add;
    treeNode[root<<1|1].add += treeNode[root].add;
    treeNode[root<<1|1].max += treeNode[root].add;
    treeNode[root].add = 0;     
}

void insert(int left, int right, int root, int val)
{   
    if(left <= treeNode[root].left && treeNode[root].right <= right )
    {
        treeNode[root].max += val;
        treeNode[root].add += val;
        return;
    }
    if(treeNode[root].add != 0)//此节点标记有延迟更新,所以更新子节点标记
        lazy(root);		//lazy 过程,把父节点变为0,并把值赋给左右节点
        
    int mid = (treeNode[root].left + treeNode[root].right)>>1;
    if(left <= mid)
        insert(left, right, root<<1, val);
    if( mid < right)
        insert(left, right, root<<1|1, val);
    
    int tmp = root<<1;//回溯,根据左右子节点,更新此节点值
    if(treeNode[root<<1].max < treeNode[root<<1|1].max)
        tmp = tmp|1;
    
    treeNode[root].max = treeNode[tmp].max;
    treeNode[root].index = treeNode[tmp].index;
}


void query(int left, int right, int root, int &maxn, int &maxi)
{   
    if(left <= treeNode[root].left  && treeNode[root].right <= right)
    {
        if(maxn < treeNode[root].max)
        {
            maxn = treeNode[root].max;
            maxi = treeNode[root].index;
        }
        return ;
    }
    
    if(treeNode[root].add !=  0)
        lazy(root); 
    
    int mid = (treeNode[root].left + treeNode[root].right) >> 1;
    if( left <= mid)
        query(left, right, root<<1, maxn, maxi);
    if(right > mid)
        query(left, right, root<<1|1, maxn, maxi);
    
}

int main()
{
    int n,m;
    int ans,ansi;
    while(scanf("%d %d",&n,&m) && n!=0 && m!=0)
    {             
        char oper;
        int a,b,c;
        build(1,n,1);
        int t=m;
        while(t--)
        {
            scanf("%s",&oper);
            if(oper=='I')
            {
                scanf("%d %d %d",&a,&b,&c);
                insert(a,b,1,c);
            }   
            else
            {
                ans = -1;
                ansi = 0;
                scanf("%d %d", &a,&b);
                query(a, b, 1, ans, ansi);
                printf("%d\n", ans);
                insert(ansi, ansi, 1, -ans);
            }
        }
    }
   //system("pause");
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值