loj 6728 6729 数列分块入门 #2 #3

 

题解:分块。用vector维护每个块,二分查找。及时更新边块即可。当前值+此块增加的值<c*c,即当前值<c*c-块同时增加的值。

 

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int w[maxn],n,block,cnt,sum[maxn];
vector<int> v[50005];
int get(int x);
void update(int l,int r,int c);
int check(int l,int r,int c);
void reset(int k);
int main()
{
  int i,op,l,r,c;
  scanf("%d",&n);
  block=sqrt(n);
  if(n%block) cnt=n/block+1;
  else cnt=n/block;
  for(i=1;i<=n;i++) 
   {
     scanf("%d",&w[i]);
     v[get(i)].push_back(w[i]);
   }
  for(i=1;i<=cnt;i++) sort(v[i].begin(),v[i].end());
  for(i=0;i<n;i++)
   {
     scanf("%d%d%d%d",&op,&l,&r,&c);
     if(op==0) update(l,r,c);
     else printf("%d\n",check(l,r,c*c));
   }
  system("pause");
  return 0;
}
int get(int x)
{return (x-1)/block+1;}
void reset(int k)
{
  v[k].clear();
  for(int i=(k-1)*block+1;i<=min(k*block,n);i++) v[k].push_back(w[i]);
  sort(v[k].begin(),v[k].end());
}
void update(int l,int r,int c)
{
  int pre,end,k;
  pre=get(l);end=get(r);
  if(pre==end) 
   {
     for(k=l;k<=r;k++) w[k]+=c;
     reset(pre);
   }
  else
   {
     for(k=l;k<=min(pre*block,n);k++) w[k]+=c;
     for(k=(end-1)*block+1;k<=r;k++) w[k]+=c;
     for(k=pre+1;k<end;k++) sum[k]+=c;
     reset(pre);reset(end);
   }
}
int check(int l,int r,int c)
{
  int ans=0,pre,end,k,x;
  pre=get(l);end=get(r);
  if(pre==end) 
   { 
     for(k=l;k<=r;k++) 
       if(w[k]+sum[pre]<c) ans++;
   }
  else
   {
     for(k=l;k<=min(pre*block,n);k++) if(w[k]+sum[get(k)]<c) ans++;
     for(k=(end-1)*block+1;k<=r;k++) if(w[k]+sum[get(k)]<c) ans++;
     for(k=pre+1;k<end;k++) 
      {
        x=c-sum[k];
        ans+=lower_bound(v[k].begin(),v[k].end(),x)-v[k].begin();
      }
   }
  return ans;
}

 

 

 

 

题解:分块。与数列分块入门 2类似,稍微修改即可。

 

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int w[maxn],n,block,cnt,sum[maxn];
vector<int> v[50005];
int get(int x);
void update(int l,int r,int c);
int check(int l,int r,int c);
void reset(int k);
int main()
{
  int i,op,l,r,c;
  scanf("%d",&n);
  block=sqrt(n);
  if(n%block) cnt=n/block+1;
  else cnt=n/block;
  for(i=1;i<=n;i++) 
   {
     scanf("%d",&w[i]);
     v[get(i)].push_back(w[i]);
   }
  for(i=1;i<=cnt;i++) sort(v[i].begin(),v[i].end());
  for(i=0;i<n;i++)
   {
     scanf("%d%d%d%d",&op,&l,&r,&c);
     if(op==0) update(l,r,c);
     else printf("%d\n",check(l,r,c));
   }
  system("pause");
  return 0;
}
int get(int x)
{return (x-1)/block+1;}
void reset(int k)
{
  v[k].clear();
  for(int i=(k-1)*block+1;i<=min(k*block,n);i++) v[k].push_back(w[i]);
  sort(v[k].begin(),v[k].end());
}
void update(int l,int r,int c)
{
  int pre,end,k;
  pre=get(l);end=get(r);
  if(pre==end) 
   {
     for(k=l;k<=r;k++) w[k]+=c;
     reset(pre);
   }
  else
   {
     for(k=l;k<=min(pre*block,n);k++) w[k]+=c;
     for(k=(end-1)*block+1;k<=r;k++) w[k]+=c;
     for(k=pre+1;k<end;k++) sum[k]+=c;
     reset(pre);reset(end);
   }
}
int check(int l,int r,int c)
{
  int ans=-0x3f3f3f3f,pre,end,k,x,flag=0;
  pre=get(l);end=get(r);
  if(pre==end) 
   { 
    for(k=l;k<=r;k++) 
     {
       if(w[k]+sum[pre]<c) 
        {
          flag=1;
          ans=max(ans,w[k]+sum[pre]);
        }
     }
   }
  else
   {
     for(k=l;k<=min(pre*block,n);k++) 
      if(w[k]+sum[get(k)]<c)
         flag=1,ans=max(ans,w[k]+sum[get(k)]);
         
     for(k=(end-1)*block+1;k<=r;k++) 
       if(w[k]+sum[get(k)]<c) 
         flag=1,ans=max(ans,w[k]+sum[get(k)]);
         
     for(k=pre+1;k<end;k++) 
      {
        x=c-sum[k];
        int index=lower_bound(v[k].begin(),v[k].end(),x)-v[k].begin();
        if(index>0&&v[k][index-1]+sum[k]<c)
         flag=1,ans=max(ans,v[k][index-1]+sum[k]);
      }
   }
  return flag==1?ans:-1;
}

 

posted @ 2019-08-05 21:22  Vivid-BinGo  阅读(221)  评论(0)    收藏  举报