Uva 12436 Rip Van Winkle's Code

本文介绍了一种解决区间更新和查询问题的高效算法,通过使用线段树结构来优化复杂度,实现了对数组数据的操作。具体包括更新特定范围内的元素值、查询特定范围内的元素和计算特定范围内的元素之和。该算法适用于需要频繁进行区间操作的场景,如在线编辑、实时数据更新等应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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. Though Rip Van Winkle is going to sleep for 20years, and his code is also super slow, you need to perform the same update operations and output theresult for the query operation S in an efficient way.

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

Input

The first line of input will contain T (≤ 4 ∗ 105) denoting the number of operations. Each of the nextT lines starts with a character (‘A’, ‘B’, ‘C’ or ‘S’), which indicates the type of operation. Character ‘A’,‘B’ or ‘S’ will be followed by two integers, st and nd in the same line. Character ‘C’ is followed by threeintegers, st, nd and x. It’s assumed that, 1 ≤ st ≤ nd ≤ 250000 and −105 ≤ x ≤ 105. The meaningsof these integers are explained by the code of Rip Van Winkle.

Output

For each line starting with the character ‘S’, print S(st, nd) as defined in the code.

Sample Input

7
A 1 4
B 2 3
S 1 3
C 3 4 -2
S 2 4
B 1 3
S 2 4

Sample Output

9

0

3

这题是区间更新,这题比较麻烦,做了很长时间。先用线段树维护l,r,add1(线段左端点加的值),add2(线段右端点加的值),step(区间的公差,右边减去左边的),sum(区间总和),flag(判断区间是否数字相同),value(区间数字都相同时的数值大小).我的思路是每一次更新,都把这一段的sum值直接表示出来,如果更新的这条线段小于当前线段,那么先不更新sum值,而是b[th].sum=b[lth].sum+b[rth].sum;


#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define lth th<<1
#define rth th<<1|1
#define inf 99999999
#define pi acos(-1.0)
#define MOD 100000007
#define maxn 250050
struct node{
    int l,r;
    ll value,flag;  //flag表示这段是不是值都是相同的,value是这段的值
    ll add1,step,add2; //add1表示左端点加的值,add2表示右端点,step表示这段的公差
    ll sum;
}b[4*maxn];

void build(int l,int r,int th)
{
    int mid;
    b[th].l=l;b[th].r=r;
    b[th].value=0;b[th].flag=1;
    b[th].add1=b[th].step=b[th].add2=0;
    b[th].sum=0;
    if(l==r)return;
    mid=(l+r)/2;
    build(l,mid,lth);
    build(mid+1,r,rth);
}
void pushdown(int th)
{
    int mid;
    mid=(b[th].l+b[th].r)/2;
    if(b[th].flag){
        b[th].flag=0;
        b[lth].flag=1;
        b[lth].value=b[th].value;
        b[lth].add1=b[lth].add2=b[lth].step=0;
        b[lth].sum=(b[lth].r-b[lth].l+1)*b[th].value;

        b[rth].flag=1;
        b[rth].value=b[th].value;
        b[rth].add1=b[rth].add2=b[rth].step=0;
        b[rth].sum=(b[rth].r-b[rth].l+1)*b[th].value;
    }

    ll add1,add2;
    add1=b[th].add1; add2=b[th].add1+(mid-b[th].l)*b[th].step;
    b[lth].add1+=add1;
    b[lth].add2+=add2;
    b[lth].step+=b[th].step;
    b[lth].sum+=(add1+add2)*(b[lth].r-b[lth].l+1)/2;

    ll add3,add4;
    add3=add2+b[th].step;add4=add3+(b[th].r-(mid+1))*b[th].step;
    b[rth].add1+=add3;
    b[rth].add2+=add4;
    b[rth].step+=b[th].step;
    b[rth].sum+=(add3+add4)*(b[rth].r-b[rth].l+1)/2;

    b[th].add1=b[th].add2=b[th].step=0;
}
void pushup(int th)
{
    b[th].sum=b[lth].sum+b[rth].sum;
}

void update(int l,int r,ll add,int f,int th)
{
    int mid;
    if(b[th].l==l && b[th].r==r){
        if(f==1){
            b[th].add1+=add;
            b[th].add2+=add+b[th].r-b[th].l;
            b[th].step+=1;
            b[th].sum+=(add+add+b[th].r-b[th].l)*(b[th].r-b[th].l+1)/2;
            return;
        }
        else if(f==2){
            b[th].add1+=add+b[th].r-b[th].l;
            b[th].add2+=add;
            b[th].step-=1;
            b[th].sum+=(add+add+b[th].r-b[th].l)*(b[th].r-b[th].l+1)/2;
            return;
        }
        else if(f==3){
            b[th].flag=1;
            b[th].value=add;
            b[th].sum=b[th].value*(b[th].r-b[th].l+1);
            b[th].add1=b[th].add2=b[th].step=0;
            return;
        }
    }
    pushdown(th);
    mid=(b[th].l+b[th].r)/2;
    if(r<=mid)update(l,r,add,f,lth);
    else if(l>mid)update(l,r,add,f,rth);
    else{
        if(f==1){
            update(l,mid,add,f,lth);
            update(mid+1,r,add+(mid+1-l),f,rth);
        }
        else if(f==2){
            update(l,mid,add+(r-mid),f,lth);
            update(mid+1,r,add,f,rth);
        }
        else if(f==3){
            update(l,mid,add,f,lth);
            update(mid+1,r,add,f,rth);
        }
    }
    pushup(th);
}
ll question(int l,int r,int th)
{
    int mid;
    if(b[th].l==l && b[th].r==r){
        return b[th].sum;
    }
    pushdown(th);
    mid=(b[th].l+b[th].r)/2;
    if(r<=mid)return question(l,r,lth);
    else if(l>mid)return question(l,r,rth);
    else{
        return question(l,mid,lth)+question(mid+1,r,rth);
    }
}
int main()
{
    int m,i,j,T,c,d;
    ll n,num;
    char s[10];
    while(scanf("%lld",&n)!=EOF)
    {
        build(1,250010,1);
        for(i=1;i<=n;i++){
            scanf("%s%d%d",s,&c,&d);
            if(s[0]=='A'){
                update(c,d,1,1,1);
            }
            else if(s[0]=='B'){
                update(c,d,1,2,1);
            }
            else if(s[0]=='C'){
                scanf("%lld",&num);
                update(c,d,num,3,1);
            }
            else if(s[0]=='S'){
                printf("%lld\n",question(c,d,1) );
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值