BZOJ 3922:Karin的弹幕 【线段树】+【暴力】

题意:

给定一个序列,支持以下操作:①对一段下标是等差数列的子序列进行求最大值操作(参见输入格式);②单点修改。

不知怎么回事,29号下午许多神犇好像在组队做这题。。于是ZMOIYNLP、Angelic47神犇邀请我这个蒟蒻一起做。。。。。
其实想法很简单,建许多线段树,不在线段树的情况暴力。线段树太多会MLE,太少时间效率我们认为不高(事实证明这是不准确的)。。。
于是我就把步长为100以下所有都建了线段树。。。。。发现T了。。。
然后我就乱搞,试图减小常数。。。但见效甚微
我们偶然的只把步长为4以下所有建了线段树。。。就飞快了。。。BZOJ上当前排第三。。
ZMOIYNLP的分块马上就要超过我啦!!!Angelic47的神奇算法也即将一飞冲天!!!


var
    a:array[0..70001]of longint;
    lch,rch,maxx:array[0..10000000]of longint;//事实上还是开大了
    ed,root:array[0..200,0..200]of longint;//ed[i,j]表示步长为i,从原序列中第j个开始的等差子序列的长度。root[i,j]表示步长为i,从原序列中第j个开始的等差子序列在线段树中的根
    n,m,i,x,y,tot,step,st,bound,rt,ans,op,up:longint;

function max(a,b:longint):longint;inline;
    begin
        if a>b then exit(a);exit(b);
    end;

procedure build(l,r,i:longint);
    var mid:longint;
    begin
        if l=r then begin maxx[i]:=a[st+(l-1)*step];exit;end;
        mid:=(l+r)>>1;
        inc(tot);
        lch[i]:=tot;
        build(l,mid,lch[i]);
        inc(tot);
        rch[i]:=tot;
        build(mid+1,r,rch[i]);
        //maxx[i]:=max(maxx[lch[i]],maxx[rch[i]]);
        if maxx[lch[i]]>maxx[rch[i]] then maxx[i]:=maxx[lch[i]] else maxx[i]:=maxx[rch[i]];
    end;

function get(s,t,l,r,i:longint):longint;
    var mid,a,b:longint;
    begin
        if (s<=l)and(t>=r) then exit(maxx[i]);
        mid:=(l+r)>>1;
        if s>mid then exit(get(s,t,mid+1,r,rch[i]));
        if t<=mid then exit(get(s,t,l,mid,lch[i]));
        //exit(max(get(s,t,l,mid,lch[i]),get(s,t,mid+1,r,rch[i])));
        a:=get(s,t,l,mid,lch[i]);
        b:=get(s,t,mid+1,r,rch[i]);
        if a>b then exit(a) else exit(b);
    end;

procedure update(p,l,r,i:longint);
    var mid:longint;
    begin
        if l=r then begin maxx[i]:=a[st+(p-1)*step];exit;end;
        mid:=(l+r)>>1;
        if p<=mid then update(p,l,mid,lch[i]) else update(p,mid+1,r,rch[i]);
        //maxx[i]:=max(maxx[lch[i]],maxx[rch[i]]);
        //我原来脑残的打了maxx[i]:=max(lch[i],rch[i]);结果蹦出来许多很大的数
        if maxx[lch[i]]>maxx[rch[i]] then maxx[i]:=maxx[lch[i]] else maxx[i]:=maxx[rch[i]];
    end;

begin
    up:=4;
    //assign(input,'in');reset(input);
    readln(n);
    if n<up then bound:=n else bound:=up;
    for i:=1 to n do read(a[i]);
    for step:=1 to bound do
        for st:=1 to step do
            begin
                inc(tot);
                root[step,st]:=tot;
                ed[step,st]:=(n-st)div step+1;
                build(1,ed[step,st],tot);
            end;
    //writeln(tot);
    readln(m);
    for m:=1 to m do
        begin
            readln(op,x,y);
            case op of
                1:
                    begin
                        if y>bound then//暴力
                            begin
                                //pos:=x;
                                ans:=-maxlongint;
                                while x<=n do
                                    begin
                                        if a[x]>ans then ans:=a[x];
                                        x:=x+y;
                                    end;
                                writeln(ans);
                                continue;
                            end;
                        st:=(x-1)mod y+1;
                        rt:=root[y,st];
                        ans:=get((x-st)div y+1,ed[y,st],1,ed[y,st],rt);
                        writeln(ans);
                    end;        
                0:
                    begin
                        inc(a[x],y);
                        for step:=1 to bound do
                            begin
                                st:=(x-1)mod step+1;
                                rt:=root[step,st];
                                update((x-st)div step+1,1,ed[step,st],rt);
                            end;
                    end;
            end;
        end;
    close(input);close(output);
end.

【后记】好了,ZMOIYNLP已经第一啦!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值