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

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

时间: 2024-10-10 02:02:51

UVA-12436 Rip Van Winkle's Code (线段树区间更新)的相关文章

uva 12436 - Rip Van Winkle&#39;s Code(线段树)

题目链接:uva 12436 - Rip Van Winkle's Code 题目大意:四种操作,操作见题目. 解题思路:即用线段树维护一个等差数列,因为一个等差加上一个等差还是一个等差数列,所以对于每个节点记录区 间左端的值,也就是首项,以及公差即可.因为还有一个S操作,所以要开一个标记记录区间值是否相同. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; ty

UVA 12436 - Rip Van Winkle&#39;s Code(线段树)

UVA 12436 - Rip Van Winkle's Code 题目链接 题意:区间修改一个添加等差数列,一个把区间设为某个值,然后询问区间和 思路:关键在于等差数列的地方,线段树的每个结点添加一个首项和公差,由于等差数列加上一个等差数列还是一个等差数列,利用这个性质就可以进行维护了,注意set操作会覆盖掉等差数列的操作 代码: #include <cstdio> #include <cstring> #define lson(x) ((x<<1)+1) #defi

Uva 12436 Rip Van Winkle&#39;s Code

Rip Van Winkle was fed up with everything except programming. One day he found a problem whichrequired to perform three types of update operations (A, B, C), and one query operation S over an arraydata[]. Initially all elements of data are equal to 0

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新

题目来源:Light OJ 1411 Rip Van Winkle`s Code 题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,...或者从右到左加上...3,2,1 或者把某个区间的数都置为v 思路:我是加了6个域 add是这段区间每个数都要加上add  add是这么来的 对与123456...这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3 v是这个区间都要置为v 他的优先级最高 b是

Uva 1232 - SKYLINE ( 线段树 + 区间更新 )

Uva 1232 SKYLINE (线段树 + 区间更新) 题意: 按照顺序在地面上建造放在,每个房子的高度为h,操作 l r h 表示 在(l,r] 区间建立一个高度为h的房子.统计每次建立完房子之后的overlap值之和 overlap值表示[ 修完一座房子之后,统计它在多长的部分是最高的(可以和其他房子并列高) ]如样例图,按照灰.黒.白的顺序建立房子 ans = (11-5) + (5-1) + (5-3) + (13-11) = 6 + 4 + 4 = 14 分析: 一开始一直想不明白

HDU 4614 Vases and Flowers(线段树区间更新+二分)

Problem Description Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A a

线段树区间更新+向量知识——POJ 2991

对应POJ题目:点击打开链接 Crane Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description ACM has bought a new crane (crane -- je?áb) . The crane consists of n segments of various lengths, connected by flexible joints

HDU 1689 Just a Hook 线段树区间更新求和

点击打开链接 Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 18894    Accepted Submission(s): 9483 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <