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
#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);
}
}
}
}
}