标签:
题意:
long long data[250001];
void A( int st, int nd ) { for( int i = st; i \le nd; i++ ) data[i] = data[i] + (i - st + 1); }
void B( int st, int nd ) { for( int i = st; i \le nd; i++ ) data[i] = data[i] + (nd - i + 1); }
void C( int st, int nd, int x ) { for( int i = st; i \le nd; i++ ) data[i] = x; }
long long S( int st, int nd ) { long long res = 0; for( int i = st; i \le nd; i++ ) res += data[i]; return res; }
四个函数,对应四种操作A、B、C、S给出m个操作,求s操作时返回的结果。
分析:
明显的线段树的区间更新,但懒惰标记的选择要想一想,C这个操作好处理、我们观察A、B发现都是加上一个等差数列、等差数列加等差数列还是等差数列、那我们选择等差数列的首项和公差做标记。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<1|1 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) #define N 250001 const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; struct node{ ll a1,d,sum,setv; int l,r; }t[N<<2]; void pushup(int rt){ t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum; } void pushdown(int rt){ if(t[rt].setv!=INF){ t[rt<<1].setv=t[rt<<1|1].setv=t[rt].setv; t[rt<<1].a1=t[rt<<1].d=t[rt<<1|1].a1=t[rt<<1|1].d=0; t[rt<<1].sum=1LL*(t[rt<<1].r-t[rt<<1].l+1)*t[rt].setv; t[rt<<1|1].sum=1LL*(t[rt<<1|1].r-t[rt<<1|1].l+1)*t[rt].setv; t[rt].setv=INF; } if(t[rt].a1||t[rt].d){ ll len1=t[rt<<1].r-t[rt<<1].l+1; ll len2=t[rt<<1|1].r-t[rt<<1|1].l+1; ll tmp1=t[rt].a1; ll tmp2=tmp1+len1*t[rt].d; t[rt<<1].a1+=tmp1; t[rt<<1|1].a1+=tmp2; t[rt<<1].d+=t[rt].d; t[rt<<1|1].d+=t[rt].d; t[rt<<1].sum+=tmp1*len1+len1*(len1-1)/2*t[rt].d;//等差数列求和 t[rt<<1|1].sum+=tmp2*len2+len2*(len2-1)/2*t[rt].d; t[rt].a1=t[rt].d=0; } } void build(int l,int r,int rt){ t[rt].l=l; t[rt].r=r; t[rt].sum=t[rt].a1=t[rt].d=0; t[rt].setv=INF; if(l==r)return; int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update_add(int l,int r,int rt,ll d){ if(l<=t[rt].l&&r>=t[rt].r){ ll a1=(d==1)?(t[rt].l-l+1):(r-t[rt].l+1);//确定首项 ll len=t[rt].r-t[rt].l+1; t[rt].a1+=a1; t[rt].d+=d; t[rt].sum+=a1*len+len*(len-1)/2*d; return; } pushdown(rt); int m=(t[rt].l+t[rt].r)>>1; if(l<=m)update_add(l,r,rt<<1,d); if(r>m)update_add(l,r,rt<<1|1,d); pushup(rt); } void update_set(int l,int r,int rt,ll x){ if(l<=t[rt].l&&r>=t[rt].r){ t[rt].setv=x; t[rt].a1=t[rt].d=0; t[rt].sum=1LL*(t[rt].r-t[rt].l+1)*x; return; } pushdown(rt); int m=(t[rt].l+t[rt].r)>>1; if(l<=m)update_set(l,r,rt<<1,x); if(r>m)update_set(l,r,rt<<1|1,x); pushup(rt); } ll query(int l,int r,int rt){ if(l<=t[rt].l&&r>=t[rt].r){ return t[rt].sum; } pushdown(rt); ll num=0; int m=(t[rt].l+t[rt].r)>>1; if(l<=m)num+=query(l,r,rt<<1); if(r>m)num+=query(l,r,rt<<1|1); return num; } int main() { int n,tll,trr; ll x; char op[3]; build(1,N,1); scanf("%d",&n); while(n--){ scanf("%s%d%d",op,&tll,&trr); if(op[0]==‘A‘){ update_add(tll,trr,1,1); } else if(op[0]==‘B‘) update_add(tll,trr,1,-1); else if(op[0]==‘C‘){ scanf("%lld",&x); update_set(tll,trr,1,x); } else if(op[0]==‘S‘){ printf("%lld\n",query(tll,trr,1)); } } return 0; }
UVA 12436-Rip Van Winkle's Code(线段树的区间更新)
标签:
原文地址:http://www.cnblogs.com/zsf123/p/4719100.html