码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ3922】Karin的弹幕 线段树&暴力

时间:2015-04-10 15:42:11      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:bzoj3922   karin的弹幕   线段树   暴力   

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44978599");
}

题解:

我们对每个等差数列维护一棵线段树。
比如等差为 5n17 ,则线段树内节点顺序为:
1611162712173813491451015

然后查询的时候到对应线段树内查询一段就好了。
然后等差太大 (>5) 就不用维护线段树了,数量不会太多(虽然依然不少),直接暴力比较就行了。

实测:

下图由上至下分别维护到了: 873465
技术分享

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 300000
#define M 5
#define ls (note<<1)
#define rs (note<<1|1)
#define inf 0x3f3f3f3f
using namespace std;
int src[N],n,m;
struct Segment_Tree
{
    int s[N],st[N],en[N],crs[N],t[N];
    void pushup(int note)
    {
        s[note]=max(s[ls],s[rs]);
    }
    void build(int note=1,int l=1,int r=n)
    {
        if(l==r)
        {
            s[note]=t[l];
            crs[l]=note;
            return ;
        }
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(note);
    }
    void init(int d)
    {
        int p=0;
        for(int i=1;i<=d;i++)
        {
            for(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)
    {
        s[x=crs[st[x]]]+=w;
        for(x>>=1;x;x>>=1)pushup(x);
    }
    int query(int l,int r,int note=1,int L=1,int R=n)
    {
        if(L==l&&r==R)return s[note];
        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]);}
}s[M+1];
int main()
{
//  freopen("test.in","r",stdin);

    int i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&src[i]);
    for(i=1;i<=M;i++)s[i].init(i);
    for(scanf("%d",&m);m--;)
    {
        scanf("%d%d%d",&i,&j,&k);
        if(i==0)
        {
            src[j]+=k;
            for(i=1;i<=M;i++)s[i].add(j,k);
        }
        else {
            if(k==0)printf("%d\n",src[j]);
            else if(k>M)
            {
                int ans=-inf;
                while(j<=n)ans=max(ans,src[j]),j+=k;
                printf("%d\n",ans);
            }
            else printf("%d\n",s[k].ask(j));
        }
    }
    return 0;
}

【BZOJ3922】Karin的弹幕 线段树&暴力

标签:bzoj3922   karin的弹幕   线段树   暴力   

原文地址:http://blog.csdn.net/vmurder/article/details/44978599

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