1 数列分块入门_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

using namespacestd;

typedeflong longll;const int MAXN = 50000 + 10;const int M = 225;

inlineintread()

{charch;int fl=1;int x=0;do{

ch=getchar();if(ch=='-')

fl=-1;

}while(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];intmain()

{

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

#pragma GCC optimize(2)

#pragma GCC optimize(3)

using namespacestd;

inlinecharnc()

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

}

inlineintread()

{charch;int fl=1;int x=0;do{

ch=nc();if(ch=='-')

fl=-1;

}while(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;structp_tree

{intsum;intlcc;intrcc;

} ;

p_tree t[MAXN*25];int root[MAXN],cnt=0;structnode

{intval;intid;

friendbool operator

{return a1.val

}

};

node a[MAXN];intc[MAXN];intzsi,zsz;boolbz;intck;

inlinevoid update(int& rt,int x,int k,int l,intr)

{

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);

}

inlinevoid query(int l,int r,int x,inty)

{if(bz) return;if(x==y)

{if(zsz

{

zsz=t[r].sum-t[l].sum;

zsi=x;

}if(zsz>(ck)/2)

{

bz= true;

}return;

}else{if(zsz

{

query(t[l].lcc,t[r].lcc,x,(x+y)>>1);

}if(zsz

{

query(t[l].rcc,t[r].rcc,((x+y)>>1)+1,y);

}

}

}intn,q;intrankk[MAXN];intmain()

{

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

后面的留坑

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值