第一讲:区间加减,单点查询
复杂度:
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
const int n1,blo;
vector<int> a,block,tag;
vector<vector<int> > ve;
fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5,0),ve(n2+5)
{
for(int i=1;i<=nn;i++)
a[i]=a2[i];
for(int i=1;i<=nn;i++)
{
block[i]=(i-1)/blo+1;
ve[block[i]].push_back(a[i]);
}
}
void add(int l,int r,int x)
{
for(int i=l;i<=min(block[l]*blo,r);i++)
a[i]+=x;
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
a[i]+=x;
}
for(int i=block[l]+1;i<=block[r]-1;i++)
tag[i]+=x;
}
int query(int x)
{
return a[x]+tag[block[x]];
}
};
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
vector<int> a(n+5);
for(int i=1;i<=n;i++)
cin>>a[i];
fenkuai fk1(n,a,sqrt(n));
while(n--)
{
int nb,l,r,c;
l++;
r++;
cin>>nb>>l>>r>>c;
if(nb==0)
fk1.add(l,r,c);
else
cout<<fk1.query(r)<<endl;
}
return 0;
}
第二讲:区间加减,查询区间内小于x的数的个数
复杂度:
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
const int n1,blo;
vector<int> a,block,tag;
vector<vector<int> > ve;
fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5),ve(n2+5)
{
for(int i=1;i<=nn;i++)
a[i]=a2[i];
for(int i=1;i<=nn;i++)
{
block[i]=(i-1)/blo+1;
ve[block[i]].push_back(a[i]);
}
for(int i=1;i<=block[nn];i++)
sort(ve[i].begin(),ve[i].end());
}
void reset(int x)
{
ve[x].clear();
for(int i=(x-1)*blo+1;i<=min(x*blo,n1);i++)
ve[x].push_back(a[i]);
sort(ve[x].begin(),ve[x].end());
}
void add(int l,int r,int x)
{
for(int i=l;i<=min(block[l]*blo,r);i++)
a[i]+=x;
reset(block[l]);
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
a[i]+=x;
reset(block[r]);
}
for(int i=block[l]+1;i<=block[r]-1;i++)
tag[i]+=x;
}
int query(int l,int r,int c)
{
int ans=0;
for(int i=l;i<=min(block[l]*blo,r);i++)
{
if(a[i]+tag[block[l]]<c)
ans++;
}
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
if(a[i]+tag[block[r]]<c)
ans++;
}
for(int i=block[l]+1;i<=block[r]-1;i++)
{
int x=c-tag[i];
ans+=lower_bound(ve[i].begin(),ve[i].end(),x)-ve[i].begin();
}
return ans;
}
};
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;k=n;
vector<int> a(n+5);
for(int i=1;i<=n;i++)
cin>>a[i];
fenkuai fk1(n,a,sqrt(n));
while(k--)
{
int nb,l,r,c;
cin>>nb>>l>>r>>c;
if(nb==0)
fk1.add(l,r,c);
else
cout<<fk1.query(l,r,c*c)<<endl;
}
return 0;
}
第三讲:区间加减 ,找x的前驱(区间内比x小的最大元素)
复杂度:
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
const int n1,blo;
vector<int> a,block,tag;
vector<vector<int> > ve;
fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5),ve(n2+5)
{
for(int i=1;i<=nn;i++)
a[i]=a2[i];
for(int i=1;i<=nn;i++)
{
block[i]=(i-1)/blo+1;
ve[block[i]].push_back(a[i]);
}
for(int i=1;i<=block[nn];i++)
sort(ve[i].begin(),ve[i].end());
}
void reset(int x)
{
ve[x].clear();
for(int i=(x-1)*blo+1;i<=min(x*blo,n1);i++)
ve[x].push_back(a[i]);
sort(ve[x].begin(),ve[x].end());
}
void add(int l,int r,int x)
{
for(int i=l;i<=min(block[l]*blo,r);i++)
a[i]+=x;
reset(block[l]);
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
a[i]+=x;
reset(block[r]);
}
for(int i=block[l]+1;i<=block[r]-1;i++)
tag[i]+=x;
}
int query(int l,int r,int c)
{
int ans=-inf*inf;
for(int i=l;i<=min(block[l]*blo,r);i++)
{
if(a[i]+tag[block[l]]<c)
ans=max(ans,a[i]+tag[block[l]]);
}
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
if(a[i]+tag[block[r]]<c)
ans=max(ans,a[i]+tag[block[r]]);
}
for(int i=block[l]+1;i<=block[r]-1;i++)
{
int x=c-tag[i];
auto it=lower_bound(ve[i].begin(),ve[i].end(),x);//找到块中第一个大于等于x的值
if(it!=ve[i].begin())
{
it--;
ans=max(ans,*it+tag[i]);//这里要加上tag[i]
}
}
if(ans!=-inf*inf)
return ans;
else
return -1;
}
};
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;k=n;
vector<int> a(n+5);
for(int i=1;i<=n;i++)
cin>>a[i];
fenkuai fk1(n,a,sqrt(n));
while(k--)
{
int nb,l,r,c;
cin>>nb>>l>>r>>c;
if(nb==0)
fk1.add(l,r,c);
else
cout<<fk1.query(l,r,c)<<endl;
}
return 0;
}
第四讲:区间加减,区间求和并模(c+1)
复杂度:
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
const int n1,blo;
vector<int> a,block,tag,sum;
vector<vector<int> > ve;
fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5,0),sum(nn+5,0),ve(n2+5)
{
for(int i=1;i<=nn;i++)
a[i]=a2[i];
for(int i=1;i<=nn;i++)
{
block[i]=(i-1)/blo+1;
sum[block[i]]+=a[i];
}
}
void add(int l,int r,int x)
{
for(int i=l;i<=min(block[l]*blo,r);i++)
{
a[i]+=x;
sum[block[i]]+=x;
}
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
{
a[i]+=x;
sum[block[i]]+=x;
}
}
for(int i=block[l]+1;i<=block[r]-1;i++)
{
tag[i]+=x;
sum[i]+=x*blo;
}
}
int query(int l,int r,int c)
{
int ans=0;
for(int i=l;i<=min(block[l]*blo,r);i++)
ans=(ans+a[i]+tag[block[i]])%c;
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
ans=(ans+a[i]+tag[block[i]])%c;
}
for(int i=block[l]+1;i<=block[r]-1;i++)
ans=(ans+sum[i])%c;
return ((ans%c)+c)%c;
}
};
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
vector<int> a(n+5);
for(int i=1;i<=n;i++)
cin>>a[i];
fenkuai fk1(n,a,sqrt(n));
while(n--)
{
int nb,l,r,c;
cin>>nb>>l>>r>>c;
if(nb==0)
fk1.add(l,r,c);
else
cout<<fk1.query(l,r,c+1)<<endl;
}
return 0;
}
第五讲: 区间开方,区间求和
复杂度:(略)
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
const int n1,blo;
vector<int> a,block,flag,sum;
fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),flag(nn+5,0),sum(nn+5,0)
{
for(int i=1;i<=nn;i++)
a[i]=a2[i];
for(int i=1;i<=nn;i++)
{
block[i]=(i-1)/blo+1;
sum[block[i]]+=a[i];
}
}
void slove_sqrt(int x)
{
if(flag[x])
return;
flag[x]=1;
sum[x]=0;
for(int i=(x-1)*blo+1;i<=x*blo;i++)
{
a[i]=sqrt(a[i]);
sum[x]+=a[i];
if(a[i]>1)
flag[x]=0;
}
}
void add(int l,int r,int x)
{
for(int i=l;i<=min(block[l]*blo,r);i++)
{
sum[block[i]]-=a[i];
a[i]=sqrt(a[i]);
sum[block[i]]+=a[i];
}
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
{
sum[block[i]]-=a[i];
a[i]=sqrt(a[i]);
sum[block[i]]+=a[i];
}
}
for(int i=block[l]+1;i<=block[r]-1;i++)
slove_sqrt(i);
}
int query(int l,int r)
{
int ans=0;
for(int i=l;i<=min(block[l]*blo,r);i++)
ans+=a[i];
if(block[l]!=block[r])
{
for(int i=(block[r]-1)*blo+1;i<=r;i++)
ans+=a[i];
}
for(int i=block[l]+1;i<=block[r]-1;i++)
ans+=sum[i];
return ans;
}
};
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
vector<int> a(n+5);
for(int i=1;i<=n;i++)
cin>>a[i];
fenkuai fk1(n,a,sqrt(n));
while(n--)
{
int nb,l,r,c;
cin>>nb>>l>>r>>c;
if(nb==0)
fk1.add(l,r,c);
else
cout<<fk1.query(l,r)<<endl;
}
return 0;
}
第六讲:单点插入,单点查询
复杂度:(略)
/*
author:wuzx
*/
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
const int n1,blo;
int mm;
vector<int> a,st;
vector<vector<int> > ve;
fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),st(nn*2+5),ve(n2*2+5)
{
for(int i=1;i<=nn;i++)
a[i]=a2[i];
for(int i=1;i<=nn;i++)
ve[(i-1)/blo+1].push_back(a[i]);
mm=(nn-1)/blo+1;
}
pair<int,int> query(int b)
{
int x=1;
while(b>ve[x].size())
{
b-=ve[x].size();
x++;
}
return make_pair(x,b-1);
}
void rebuild()
{
int top=0;
for(int i=1;i<=mm;i++)
{
for(vector<int>::iterator j=ve[i].begin();j!=ve[i].end();j++)
st[++top]=*j;
ve[i].clear();
}
int blo2=sqrt(top);
for(int i=1;i<=top;i++)
ve[(i-1)/blo2+1].push_back(st[i]);
m=(top-1)/blo2+1;
}
void insert(int idx,int x)
{
pair<int,int> tt=query(idx);
ve[tt.f].insert(ve[tt.f].begin()+tt.s,x);
if(ve[tt.f].size()>20*blo)
rebuild();
}
int getnum(int idx)
{
pair<int,int> tt=query(idx);
return ve[tt.f][tt.s];
}
};
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;k=n;
vector<int> a(n+5);
for(int i=1;i<=n;i++)
cin>>a[i];
fenkuai fk1(n,a,sqrt(n));
while(k--)
{
int nb,l,r,c;
cin>>nb>>l>>r>>c;
if(nb==0)
fk1.insert(l,r);
else
cout<<fk1.getnum(r)<<endl;
}
return 0;
}