码迷,mamicode.com
首页 > Windows程序 > 详细

UVA-12436 Rip Van Winkle's Code (线段树区间更新)

时间:2016-06-17 11:01:57      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:一个数组,四种操作:

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

 

UVA-12436 Rip Van Winkle's Code (线段树区间更新)

标签:

原文地址:http://www.cnblogs.com/20143605--pcx/p/5593235.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!