UVA-12436 Rip Van Winkle's Code (线段树区间更新)
题目大意:一个数组,四种操作:
long long data[250001];
void A( int st, int nd ) {
for( int i = st; i <= nd; i++ ) data[i] = data[i] + (i - st + 1);
}
void B( int st, int nd ) {
for( int i = st; i <= nd; i++ ) data[i] = data[i] + (nd - i + 1);
}
void C( int st, int nd, int x ) {
for( int i = st; i <= nd; i++ ) data[i] = x;
}
long long S( int st, int nd ) {
long long res = 0;
for( int i = st; i <= nd; i++ ) res += data[i];
return res;
}
模拟这四种操作。
题目分析:三种更新操作,一种询问操作。三种更新实际上是两种,add更新(等差数列做加减运算仍是等差数列)和set更新,add更新的懒标记记录首项、尾项和公差。
代码如下:
# include<bits/stdc++.h> using namespace std; # define LL long long # define mid (l+(r-l)/2) const int N=250000; struct Node { LL sum; LL x,d,st,ed; bool lazy_set; bool lazy_add; }; Node tr[(N+5)*4+100]; char op[2]; void clear_lazy(int rt) { tr[rt].lazy_add=false; tr[rt].d=tr[rt].st=tr[rt].ed=0; } void change1(int rt,int l,int r,LL st,LL ed,LL d) { tr[rt].lazy_add=true; tr[rt].sum+=(LL)(r-l+1)*(st+ed)/2; tr[rt].st+=st; tr[rt].ed+=ed; tr[rt].d+=d; } void change2(int rt,int l,int r,LL x) { tr[rt].lazy_set=true; tr[rt].sum=(LL)(r-l+1)*x; tr[rt].x=x; clear_lazy(rt); } void pushUp(int rt) { tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; } void pushDown(int rt,int l,int r) { if(tr[rt].lazy_set){ change2(rt<<1,l,mid,tr[rt].x); change2(rt<<1|1,mid+1,r,tr[rt].x); tr[rt].lazy_set=false; } if(tr[rt].lazy_add){ LL st=tr[rt].st; LL ed=tr[rt].ed; int d=tr[rt].d; change1(rt<<1,l,mid,st,st+d*(mid-l),d); change1(rt<<1|1,mid+1,r,st+d*(mid-l+1),ed,d); clear_lazy(rt); } } void build(int rt,int l,int r) { tr[rt].lazy_set=false; tr[rt].lazy_add=false; tr[rt].sum=tr[rt].d=0; tr[rt].st=tr[rt].ed=0; if(l==r) return ; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void update1(int rt,int l,int r,int L,int R,LL d) { if(L<=l&&r<=R){ if(d>0){ change1(rt,l,r,l-L+1,r-L+1,d); }else{ change1(rt,l,r,R-l+1,R-r+1,d); } }else{ pushDown(rt,l,r); if(L<=mid) update1(rt<<1,l,mid,L,R,d); if(R>mid) update1(rt<<1|1,mid+1,r,L,R,d); pushUp(rt); } } void update2(int rt,int l,int r,LL L,LL R,LL x) { if(L<=l&&r<=R){ change2(rt,l,r,x); }else{ pushDown(rt,l,r); if(L<=mid) update2(rt<<1,l,mid,L,R,x); if(R>mid) update2(rt<<1|1,mid+1,r,L,R,x); pushUp(rt); } } LL query(int rt,int l,int r,LL L,LL R) { if(L<=l&&r<=R) return tr[rt].sum; pushDown(rt,l,r); LL res=0; if(L<=mid) res+=query(rt<<1,l,mid,L,R); if(R>mid) res+=query(rt<<1|1,mid+1,r,L,R); return res; } int main() { //freopen("in.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF) { build(1,1,N); LL a,b,c; while(n--) { scanf("%s",op); if(op[0]=='A'){ scanf("%lld%lld",&a,&b); update1(1,1,N,a,b,1ll); }else if(op[0]=='B'){ scanf("%lld%lld",&a,&b); update1(1,1,N,a,b,-1ll); }else if(op[0]=='C'){ scanf("%lld%lld%lld",&a,&b,&c); update2(1,1,N,a,b,c); }else{ scanf("%lld%lld",&a,&b); printf("%lld\n",query(1,1,N,a,b)); } } } return 0; }