BZOJ3922 Karin的弹幕 [线段树]

F.A.QsHomeDiscussProblemSetStatusRanklist1 Contest入门OJModifyUser   Sakura_LemonLogout捐赠本站


Notice:九月份月赛将于本周五晚六点到十一点进行,欢迎大家参加,鸣谢Claris主持,欢迎进群633587999交流!



Problem 3922. – Karin的弹幕

3922: Karin的弹幕

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 607   Solved: 231
[ Submit][ Status][ Discuss]

Description

Karin在战斗之余的闲暇时光里喜欢上B站看鬼畜视频,尤其喜欢发弹幕。她这天对一个视频的弹幕产生了兴趣,她记录了每个时间点的弹幕数量,并且可能对一段呈等差数列的时间的弹幕数量求最大值;她还可能修改某个时间点的弹幕数量。
为了不在Yuuna面前暴露出她弱爆了的数学能力,保持她傲娇的属性,你需要帮助她。
精简题意:给定一个序列,支持以下操作:①对一段下标是等差数列的子序列进行求最大值操作(参见输入格式);②单点修改。

Input

第一行是一个整数n,
第二行是一个长度为n的整数序列a1…an,
第三行是一个整数m,
接下来m行,每行首先有一个整数op,
然后,若op=0,则之后有两个整数p,v,代表将a[p]的值加上v,
若op=1,则之后有两个整数x0,d,代表询问max{a[x0],a[x0+d],a[x0+2d],…,a[x0+kd]}(x0+kd<=n,x0+(k+1)d>n)。
数据中可能有多余空格。

Output

对每个op=1,单独输出一行,代表该等差子序列的最大值。

Sample Input


【输入样例1】

10

1 6 1 4 9 4 8 2 8 5

10

1 3 3

0 5 4

0 3 8

1 2 5

1 4 8

1 7 5

1 3 6

0 1 2

1 5 3

1 4 9



【输入样例2】

10

-9 -6 2 -10 -2 -6 10 6 -4 -2

10

1 2 3

1 6 3

0 7 8

0 4 -6

0 10 -5

1 10 4

0 3 -8

1 2 4

0 10 -5

1 1 2

Sample Output


【输出样例1】

8

8

4

8

9

13

4



【输出样例2】

6

-4

-7

-6

18

HINT


【数据范围】


1<=n<=70000,


1<=m<=70000,


保证任何时刻abs(a[i])(1<=i<=n)<=2147483647,


0<=op<=1,


1<=p<=n,


abs(v)<=2147483647


1<=x0<=n,


1<=d<=n,


保证涉及的所有数在C++的int内。


2015.4.2新加四组数据




Source


本题题意就是对每个等差数列维护一棵线段树。
网上的大佬说差值为5好,那就5吧。。。。。
第一次把线段树写入struct中。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ls rt<<1
#define rs rt<<1|1
const int INF = 0x3f3f3f3f,N=3e5,M=5;
using namespace std;
int src[N],n,m;
struct Segment_Tree{
    int sum[N],st[N],en[N],c[N],t[N];
    void up(int rt){
        sum[rt]=max(sum[ls],sum[rs]);
    }
    void build(int rt=1,int l=1,int r=n){
        if(l==r){
            sum[rt]=t[l],c[l]=rt;return ;
        }
        int mid=l+r>>1;
        build(ls,l,mid),build(rs,mid+1,r),up(rt);
    }
    void init(int d){
        int p=0;
        for(register int i=1;i<=d;i++){
            for(register int k=i;k<=n;k+=d)
                st[k]=++p,t[p]=src[k];
            for(int k=i;k<=n;k+=d)en[k]=p;
        }
        build();
    }
    void add(int x,int w){
        sum[x=c[st[x]]]+=w;
        for(x>>=1;x;x>>=1)up(x);
    }
    int query(int l,int r,int rt=1,int L=1,int R=n){
        if(L==l&&r==R)return sum[rt];
        register int mid=(L+R)>>1;
        if(r<=mid)return query(l,r,ls,L,mid);
        else if(l>mid)return query(l,r,rs,mid+1,R);
        else return max(query(l,mid,ls,L,mid),query(mid+1,r,rs,mid+1,R));
    }
    int ask(int x){return query(st[x],en[x]);}
}a[M+1];
template<class T>inline void read(T &res){
    static char ch;T flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
int main(){
    read(n);
    for(register int i=1;i<=n;i++)read(src[i]);
    for(register int i=1;i<=M;i++)a[i].init(i);
    for(read(m);m--;){
        int x,y,z;
        read(x),read(y),read(z);
        if(x==0){
            src[y]+=z;
            for(register int i=1;i<=M;i++)a[i].add(y,z);
        }else{
            if(z==0)printf("%d\n",src[y]);
            else if(z>M){
                int ans=-INF;
                while(y<=n)ans=max(ans,src[y]),y+=z;
                printf("%d\n",ans);
            }else printf("%d\n",a[z].ask(y));
        }
    }
    return 0;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值