HDU 4973 A simple simulation problem(区间更新,成段查询)
题意:初始时,在一个区间中有n种数,每种个数为1;
两种操作:
D x y,使区间[x,y](包括端点)中的每种数的个数乘以2(区间长度翻倍);
Q x y,查询区间[x,y]中同一种数的最大个数;
思路:用线段树维护区间,维护区间中的总个数和最大个数;
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef __int64 ll; int t,n,m; ll a,b; char str[15]; int lazy[500010]; ll sum[500010],MAX[500100]; void pushup(int pos) { sum[pos]=sum[pos*2]+sum[pos*2+1]; MAX[pos]=max(MAX[pos*2],MAX[pos*2+1]); } void pushdown(int pos) { if(lazy[pos]>0) { lazy[pos*2]+=lazy[pos]; lazy[pos*2+1]+=lazy[pos]; sum[pos*2]<<=lazy[pos]; sum[pos*2+1]<<=lazy[pos]; MAX[pos*2]<<=lazy[pos]; MAX[pos*2+1]<<=lazy[pos]; lazy[pos]=0; } } void build(int l,int r,int pos) { if(l==r) { sum[pos]=1; MAX[pos]=1; return; } int m=(l+r)/2; build(l,m,pos*2); build(m+1,r,pos*2+1); lazy[pos]=0; pushup(pos); return; } void update(int l,int r,int pos,ll L,ll R,ll x) { if(L<=x&&(x+sum[pos]-1)<=R) { sum[pos]<<=1; MAX[pos]<<=1; lazy[pos]++; return; } if(l==r) { if(x<=L) { sum[pos]+=min(R,x+sum[pos]-1)-L+1; } else sum[pos]+=R-x+1; MAX[pos]=sum[pos]; return; } pushdown(pos); int m=(l+r)/2; ll M=x+sum[pos*2]-1; if(L<=M) update(l,m,pos*2,L,R,x); if(M<R) update(m+1,r,pos*2+1,L,R,M+1); pushup(pos); } ll query(int l,int r,int pos,ll L,ll R,ll x)//x为当前点的起始坐标 { if(L<=x&&(x+sum[pos]-1)<=R) { return MAX[pos]; } if(l==r) { if(x<=L) { return min(R,x+sum[pos]-1)-L+1; } else return R-x+1; } pushdown(pos); int m=(l+r)/2; ll M=x+sum[pos*2]-1; ll res=0; if(L<=M) res=max(res,query(l,m,pos*2,L,R,x)); if(M<R) res=max(res,query(m+1,r,pos*2+1,L,R,M+1)); return res; } int main() { int i,j,k,cas; scanf("%d",&t); for(cas=1;cas<=t;cas++) { printf("Case #%d:\n",cas); scanf("%d%d",&n,&m); build(1,n,1); for(i=0;i<m;i++) { scanf("%s%d%d",str,&a,&b); if(str[0]=='D') update(1,n,1,a,b,1); else printf("%I64d\n",query(1,n,1,a,b,1)); } } return 0; }
有些梦想现在不去实现,以后就再也没机会了!!