LOJ数列分块入门1-9(3/9)

数列分块入门1

题目描述

给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,单点查值。

第一行输入一个数字 n

第二行输入 n 个数字,第 i个数字为 ai​​,以空格隔开。

接下来输入 n 行询问,每行输入四个数字 opt、l、r、c,以空格隔开。

若 opt=0,表示将位于 [l,r]的之间的数字都加 c

若 opt=1,表示询问 ar的值(l 和 c 忽略)

Solution:

我们给每个块设置一个加法标记(就是记录这个块中元素一起加了多少),每次操作对每个整块直接O(1)标记,而不完整的块由于元素比较少,暴力修改元素的值。

每次询问时返回元素的值加上其所在块的加法标记。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int MAXN = 50000 + 10;

const int M = 225;

inline int read()
{
    char ch;
    int fl=1;
    int x=0;
    do{
      ch= getchar();
      if(ch=='-')
        fl=-1;
    }while(ch<'0'||ch>'9');
    do{
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return x*fl;
}

ll n;

ll a[MAXN];

ll opt,c,l,r;

ll now,ks;

ll add[M+10];

int main()
{
    n = read();
    ks=1;
    now=0;
    for(int i=1;i<=n;i++)
    {
        a[i] = read();
    }
    
    for(int i=1;i<=n;i++)
    {
        opt = read();l=read();r=read();c=read();
        if(opt==0)
        {
            if((l-1)/M+1!=(r-1)/M+1)
            {
            for(int j=l;j<=((l-1)/M+1)*M;j++) a[j]+=c;
            for(int j=(l-1)/M+2;j<=(r-1)/M;j++) add[j]+=c;
            for(int j=((r-1)/M)*M+1;j<=r;j++) a[j]+=c;
            }
            else
            {
                for(int j=l;j<=r;j++) a[j]+=c;
            }
        
        }
        if(opt==1)
        {
            printf("%lld\n",a[r]+add[(r-1)/M+1]);
        }
    }
}

数列分块入门2

题目描述

给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的元素个数。

solution:

考虑把原数列分成sqrt(n)块,每块维护一个有序的序列。

首先考虑加法操作:对于整块的直接维护加法标记,不是整块的暴力修改元素,然后对块内元素重排。

然后考虑查询:对于整块的由于块内元素有序,可以直接二分。对于不是整块的暴力统计。

然而我以前写的代码WA了,加上最近没时间改,所以就不放代码了。

数列分块入门3

题目描述

给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内比某个值x其小的最大元素。

Solution:

只有查询和2不一样,那改一下二分就行了QAQ

数列分块入门4

题目描述

一个长为n的数列,以及n个操作,操作涉及区间加法,区间求和

solution:

分块后维护元素和,对于整块维护一个add标记

数列分块入门9

题目描述

给出一个长为 n 的数列,以及 n 个操作,操作涉及区间众数。

solution:

不会,主席树暴力拿了一个LOJ rank1,又短又好写。(现在不是了)

代码如下:

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)

using namespace std;

inline char nc()
{
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}

inline int read()
{
    char ch;
    int fl=1;
    int x=0;
    do{
      ch= nc();
      if(ch=='-')
        fl=-1;
    }while(ch<'0'||ch>'9');
    do{
        x=(x<<3)+(x<<1)+ch-'0';
        ch=nc();
    }while(ch>='0'&&ch<='9');
    return x*fl;
}

const int MAXN = 100000+10;

struct p_tree
{
    int sum;
    int lcc;
    int rcc;    
} ;

p_tree t[MAXN*25];

int root[MAXN],cnt=0;

struct node
{
    int val;
    int id;
    friend bool operator < (node a1,node a2)
    {
        return a1.val<a2.val;    
    } 
};

node a[MAXN];

int c[MAXN];

int zsi,zsz;

bool bz; 

int ck;

inline void update(int& rt,int x,int k,int l,int r)
{
    t[++cnt]=t[rt];
    rt = cnt;
    t[rt].sum+=k;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(x<=mid) update(t[rt].lcc,x,k,l,mid);
    else update(t[rt].rcc,x,k,mid+1,r);
}

inline void query(int l,int r,int x,int y)
{
    if(bz) return;
    if(x==y)
    {
        if(zsz<t[r].sum-t[l].sum)
        {
            zsz=t[r].sum-t[l].sum;
            zsi=x;
        }
        if(zsz>(ck)/2) 
        {
            bz = true;
        }
        return;
    }
    else
    {
        if(zsz<t[t[r].lcc].sum-t[t[l].lcc].sum)
        {
            query(t[l].lcc,t[r].lcc,x,(x+y)>>1);    
        }
        if(zsz<t[t[r].rcc].sum-t[t[l].rcc].sum)
        {
            query(t[l].rcc,t[r].rcc,((x+y)>>1)+1,y);    
        } 
    } 
}

int n,q;

int rankk[MAXN];

int main()
{
    n=read();
    for(register int i=1;i<=n;i++) a[i].val=read(),a[i].id=i;;
    root[0]=0;
    t[0].sum=t[0].lcc=t[0].rcc=0;
    sort(a+1,a+n+1);
    int top=0;
    for(register int i=1;i<=n;i++)
    {
        if(a[i].val!=a[i-1].val) top++;
        c[a[i].id]=top;
        rankk[top]=a[i].val;
    }
    for(register int i=1;i<=n;i++)
    {
        root[i]=root[i-1];
        update(root[i],c[i],1,1,100000);
    }
    zsi=0,zsz=0;
    for(register int i=1;i<=n;i++)
    {
        bz = false;
        int u=read(),v=read();
 
        if(u>v) swap(u,v);
        ck = v-u+1;
        zsi = 0,zsz = 0;
        query(root[u-1],root[v],1,100000);
        printf("%d\n",rankk[zsi]);
    }
} 

我暴力似乎碾标算了。。。291ms

后面的留坑

posted @ 2018-05-02 22:00  wlzs1432  阅读(422)  评论(0编辑  收藏  举报