LibreOJ 6279,6281,6283 数列分块入门3,5,7 树状数组,分块,线段树等.

我又做了3个.

分块3

区间加,区间求某个数x的前驱(小于x的数中最大的一个).没有输出-1.
我还以为所有的数真的会小于0.吓死我了.

/*
一样的方法.
对于l,r所在的块,暴力修改重构.
对于中间的块,lazy数组标记一下.
询问的时候暴力枚举两边,中间二分求前驱,取出这些数中最大的一个.
代码与分块2相差不大.
*/
#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
inline int read(){
  re0 x=0,f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=x*10+c-'0';
  return x*(f?1:-1);
  }
inline void read(rel &x){
  x=0;re0 f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=x*10+c-'0';
  x*=f?1:-1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return pc(48);
  if (x<0) x=-x,pc('-');
  re0 bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  }
}using namespace chtholly;
using namespace std;
#define belong(x) (((x)-1)/block+1) 
#define all(u) v[u].begin(),v[u].end()
const int karen=1e5;
typedef int fuko[karen|10];
fuko a,l,r,lazy;
int n=read(),block,num;
vector<int> v[karen|10];

void buildblock()
{
re0 i;
block=sqrt(n),num=n/block+(n%block?1:0);
for (i=1;i<=num;++i) l[i]=(i-1)*block+1,r[i]=i*block;r[num]=n;
for (i=1;i<=n;++i) v[belong(i)].push_back(a[i]);
for (i=1;i<=num;++i) sort(all(i));
}

void readd(int x)
{
v[x].clear();
for (re0 i=l[x];i<=r[x];++i)
  v[x].push_back(a[i]);
sort(all(x));
}

void update(int ql,int qr,int k)
{
re0 i;
for (i=ql;i<=min(r[belong(ql)],qr);++i)
  a[i]+=k;
readd(belong(ql));
if (belong(ql)!=belong(qr))
  {
  for (i=l[belong(qr)];i<=qr;++i)
    a[i]+=k;
  readd(belong(qr));
  }
for (i=belong(ql)+1;i<belong(qr);++i) 
  lazy[i]+=k;
}

int query(int ql,int qr,int c)
{
re0 ans=-1,i;
for (i=ql;i<=min(r[belong(ql)],qr);++i)
  if (a[i]+lazy[belong(i)]<c) ans=max(ans,a[i]+lazy[belong(i)]);
if (belong(ql)!=belong(qr)) 
  {
  for (i=l[belong(qr)];i<=qr;++i)
    if (a[i]+lazy[belong(i)]<c) ans=max(ans,a[i]+lazy[belong(i)]);
  }
for (i=belong(ql)+1;i<belong(qr);++i)
  {
  int p=lower_bound(all(i),c-lazy[i])-v[i].begin();
  if (p--) ans=max(ans,v[i][p]+lazy[i]);
  }
return ans;
}

int main()
{
re0 i;
for (i=1;i<=n;++i) a[i]=read();
buildblock();
for (i=1;i<=n;++i)
  {
  re0 op=read(),l=read(),r=read(),k=read();
  if (op) write(query(l,r,k)),pl;
  else update(l,r,k);
  }
}

分块5

区间开方向下取整,询问区间和.
即使所有的数据都取最大值,开方5-6次之后就会变成1.
我们需要标记一下每一个块里面是不是都是1,如果标记为1,我们就不再修改它了.

/*
维护原数组a,每一块的数字和sum,标记tag.
分块的算法细节多到无法想象.我拍了半天找出n多错误来,终于还是1遍A掉了.
代码非常迷,我的码风也是非常差,特别是分块算法,看起来非常糟.
*/
#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{//这个读入输出优化就非常优美.下面主程序丑得不能看.
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
inline int read(){
  re0 x=0,f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=x*10+c-'0';
  return x*(f?1:-1);
  }
inline void read(rel &x){
  x=0;re0 f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=x*10+c-'0';
  x*=f?1:-1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return pc(48);
  if (x<0) x=-x,pc('-');
  re0 bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  }
}using namespace chtholly;
#define bl(x) (((x)-1)/block+1)//x belongs to which block
#define l(x) (((x)-1)*block+1)//the left point on block x
#define r(x) (min(n,(x)*block))//the right point on block x
using namespace std;
const int karen=5e4;
typedef ll fuko[karen|10];
fuko a,sum;bool tag[karen|10];
int n=read(),block;
void buildblock()
{
re0 i;
block=sqrt(n);
for (i=1;i<=n;++i) sum[bl(i)]+=a[i];
}

void readd(int x)//重新处理区间和
{
sum[x]=0;
for (re0 i=l(x);i<=r(x);++i) sum[x]+=a[i];
}

bool judge(int x)//判断标记
{
for (re0 i=l(x);i<=r(x);++i) if (a[i]>1) return 0;
return 1;
}

void update(int ql,int qr)
{
re0 i;
if (!tag[bl(ql)])
  {
  for (i=ql;i<=min(r(bl(ql)),qr);++i) a[i]=sqrt(a[i]);
  readd(bl(ql));
  if (judge(bl(ql))) tag[bl(ql)]=1;
  }
if (bl(ql)!=bl(qr)&&!tag[bl(qr)])
  {
  for (i=l(bl(qr));i<=qr;++i) a[i]=sqrt(a[i]);
  readd(bl(qr));
  if (judge(bl(qr))) tag[bl(qr)]=1;
  }
for (i=bl(ql)+1;i<bl(qr);++i) if (!tag[i])//对中间的块也是暴力修改.反正改不过几次的.
  {
  for (re0 j=l(i);j<=r(i);++j) a[j]=sqrt(a[j]);
  readd(i);
  if (judge(i)) tag[i]=1;
  }
}

ll query(int ql,int qr)
{
re0 i;rel ans=0;
for (i=ql;i<=min(r(bl(ql)),qr);++i) ans+=a[i];
if (bl(ql)!=bl(qr)) 
  for (i=l(bl(qr));i<=qr;++i) ans+=a[i];
for (i=bl(ql)+1;i<bl(qr);++i) ans+=sum[i];
return ans;
}

int main()
{
re0 i;
for (i=1;i<=n;++i) a[i]=read();
buildblock();
for (i=1;i<=n;++i) 
  {
  re0 op=read(),l=read(),r=read(),k=read();
  if (op) write(query(l,r)),pl;
  else update(l,r);
  }
}

分块7

区间加,区间乘,区间和.
经典题了.这题我懒得做,把洛谷上面模板拖过来改一下就A了.
应该不用解释了吧.注意乘法的标记一定要比加法先处理.

/*
这个代码比较老了.
*/
#include<bits/stdc++.h> Ithea Myse Valgulious //You can put something on the head file's line without punctuations,I put one girl's name on it
namespace chtholly{//fast input and output Chtholly Nota Seniorious 
#define ll long long
#define p32 putchar(' ')
#define pl puts("")
const double ten[]={1,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19};
int read(){int x=0;char c=getchar();for (;!isdigit(c);c=getchar());for (;isdigit(c);c=getchar()) x=x*10+c-'0';return x;}
int write(int x){if (!x) return putchar('0');int bit[20],i,p=0;for (;x;x/=10) bit[++p]=x%10;for (i=p;i;--i) putchar(bit[i]+48);}
int read(double &r){double x=0,t=0;int s=0,f=1;char c=getchar();for (;!isdigit(c);c=getchar()){if (c=='-') f=-1;if (c=='.') goto readt;}for (;isdigit(c)&&c!='.';c=getchar()) x=x*10+c-'0';readt:for (;c=='.';c=getchar());for (;isdigit(c);c=getchar()) t=t*10+c-'0',++s;r=(x+t/ten[s])*f;}
int read(ll &x){x=0;char c=getchar();for (;!isdigit(c);c=getchar());for (;isdigit(c);c=getchar()) x=x*10+c-'0';}
int dwrite(ll x){if (x==0) return putchar(48);int bit[20],p=0,i;for (;x;x/=10) bit[++p]=x%10;for (i=p;i>0;--i) putchar(bit[i]+48);}
int write(ll x){dwrite(x);}
int write(double x,int k=6){static int n=ten[k];if (x==0) {putchar('0'),putchar('.');for (int i=1;i<=k;++i) putchar('0');return 0;}if (x<0) putchar('-'),x=-x;ll y=(ll)(x*n)%n;x=(ll)x;dwrite(x),putchar('.');int bit[20],p=0,i;for (;p<k;y/=10) bit[++p]=y%10;for (i=p;i>0;--i) putchar(bit[i]+48);}
#undef ll
};
using namespace chtholly;
#define boss 100000
using namespace std;
typedef long long ll;
int n,m,p=10007;ll a[boss+10];
struct node{
ll val,lazy_pr,lazy_pl;//value,lazy_product,lazy_plus;
}seg[boss*4+10];

void build(int rt,int l,int r)
{
seg[rt].lazy_pr=1,seg[rt].lazy_pl=0;
if (l==r) seg[rt].val=a[l];
else 
  {
  int mid=l+r>>1;
  build(rt<<1,l,mid),build(rt<<1|1,mid+1,r);
  seg[rt].val=seg[rt<<1].val+seg[rt<<1|1].val;
  }
seg[rt].val%=p;
}

void push_down(int rt,int l,int r)
{
int mid=l+r>>1;
//son.value=son.value*fa.lazy_product+son.size*fa.lazy_plus;
seg[rt<<1].val=(seg[rt<<1].val*seg[rt].lazy_pr+seg[rt].lazy_pl*(mid-l+1))%p;
seg[rt<<1|1].val=(seg[rt<<1|1].val*seg[rt].lazy_pr+seg[rt].lazy_pl*(r-mid))%p;
seg[rt<<1].lazy_pr=(seg[rt<<1].lazy_pr*seg[rt].lazy_pr)%p;
seg[rt<<1|1].lazy_pr=(seg[rt<<1|1].lazy_pr*seg[rt].lazy_pr)%p;
seg[rt<<1].lazy_pl=(seg[rt<<1].lazy_pl*seg[rt].lazy_pr+seg[rt].lazy_pl)%p;
seg[rt<<1|1].lazy_pl=(seg[rt<<1|1].lazy_pl*seg[rt].lazy_pr+seg[rt].lazy_pl)%p;
seg[rt].lazy_pr=1,seg[rt].lazy_pl=0;
}
//product attention a line
void update_(int rt,int il,int ir,int ql,int qr,ll k)
{
if (qr<il||ql>ir) return;
if (ql<=il&&qr>=ir) 
  {
  seg[rt].val=seg[rt].val*k%p;
  seg[rt].lazy_pr=seg[rt].lazy_pr*k%p;
  seg[rt].lazy_pl=seg[rt].lazy_pl*k%p;
  return;
  }
push_down(rt,il,ir);
int mid=il+ir>>1;
update_(rt<<1,il,mid,ql,qr,k);
update_(rt<<1|1,mid+1,ir,ql,qr,k);
seg[rt].val=(seg[rt<<1].val+seg[rt<<1|1].val)%p;
}
//plus
void update(int rt,int il,int ir,int ql,int qr,ll k)
{
if (qr<il||ql>ir) return;
if (ql<=il&&qr>=ir) 
  {
  seg[rt].lazy_pl=(seg[rt].lazy_pl+k)%p;
  seg[rt].val=(seg[rt].val+k*(ir-il+1))%p;
  return;
  }
push_down(rt,il,ir);
int mid=il+ir>>1;
update(rt<<1,il,mid,ql,qr,k);
update(rt<<1|1,mid+1,ir,ql,qr,k);
seg[rt].val=(seg[rt<<1].val+seg[rt<<1|1].val)%p;
}

ll query(int rt,int il,int ir,int ql,int qr)
{
if (qr<il||ql>ir) return 0;
if (ql<=il&&qr>=ir) return seg[rt].val;
push_down(rt,il,ir);
int mid=il+ir>>1;
return (query(rt<<1,il,mid,ql,qr)+query(rt<<1|1,mid+1,ir,ql,qr))%p;
}

int main()
{
int i;
n=read();
for (i=1;i<=n;++i) read(a[i]);
build(1,1,n);
for (i=1;i<=n;++i)
  {
  int k=read(),l=read(),r=read();ll x;read(x);
  if (k==1) update_(1,1,n,l,r,x);
  else if (!k) update(1,1,n,l,r,x);
  else write(query(1,1,n,r,r)),pl;
  }
}

Thank you very much!

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/79840159
今日推荐