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

来源:互联网 发布:编程push是什么意思啊 编辑:程序博客网 时间:2024/06/05 04:05

链接:

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

题解:

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

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

实测:

下图由上至下分别维护到了: 873465
Karin弹幕维护等差时间实测图

代码:

#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 0x3f3f3f3fusing 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;}
0 0
原创粉丝点击