hdu 4973 A simple simulation problem.(2014 Multi-University Training Contest 10)

A simple simulation problem.

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 392    Accepted Submission(s): 155


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 <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=50010;
long long sum[maxn];
long long coun[maxn];
int n,m;
int low(int k)
{
    return k&(-k);
}
void add(int i,long long v)
{
    while(i<=n)
    {
        sum[i]+=v;
        i+=low(i);
    }
}
long long getsum(int k)
{
    long long ans=0;
    while(k>0)
    {
        ans+=sum[k];
        k-=low(k);
    }
    return ans;
}
int find(long long k)
{
  int mid,l=1,r=n;
  while(l<r)
  {
      mid=(l+r)>>1;
      long long temp=getsum(mid);
      if(k>temp)
      {
          l=mid+1;
      }
      else
      r=mid;
  }
  return l;
}
void update(long long l,long long r)
{
    int L=find(l);
    int R=find(r);
    if(L==R)
    {
        add(L,r-l+1);
        coun[L]+=(r-l+1);
        return;
    }
    long long x=getsum(L);
    long long y=getsum(R-1);
    add(L,x-l+1);
    coun[L]+=(x-l+1);
    add(R,r-y);
    coun[R]+=(r-y);
    for(int i=L+1;i<R;i++)
    {
        add(i,coun[i]);
        coun[i]+=coun[i];
    }
    return;
}
void quarry(long long l,long long r)
{
    int L=find(l);
    int R=find(r);
    if(L==R)
    {
        printf("%I64d\n",r-l+1);
        return;
    }
    long long maxn;
    maxn=max(getsum(L)-l+1,r-getsum(R-1));
    for(int i=L+1;i<R;i++)
    {
        if(maxn<coun[i])
        maxn=coun[i];
    }
    printf("%I64d\n",maxn);
    return;
}
int main()
{
   int t,ca=1;
   scanf("%d",&t);
   while(t--)
   {
       char s;
       long long x,y;
       scanf("%d%d",&n,&m);
       memset(sum,0,sizeof(sum));
       for(int i=1;i<=n;i++)
       {
           add(i,1);
           coun[i]=1;
       }
       printf("Case #%d:\n",ca++);
       while(m--)
       {
           scanf(" %c%I64d%I64d",&s,&x,&y);
           if(s=='D')
           {
           update(x,y);
           }
           else
           quarry(x,y);
       }
   }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值