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