数据结构部分模版
树状数组
脑子里画出这个图
\(\\\)
\(\\\)
\(\\\)
\(\\\)
1.区间查/单点改
int n,m;
int c[Max],a[Max];
int lowbit(int x){return x&-x;}
inline void add(int p,int k)
{
while(p<=n){c[p]+=k;p+=lowbit(p);}
}
inline int sum(int p)
{
int ans=0;
while(p){ans+=c[p];p-=lowbit(p);}
return ans;
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
2.差分实现区间改/单点查
int n,m;
int c[Max],a[Max];
int lowbit(int x){return x&-x;}
inline void add(int p,int k)
{
while(p<=n){c[p]+=k;p+=lowbit(p);}
}
inline int sum(int p)
{
int ans=0;
while(p){ans+=c[p];p-=lowbit(p);}
return ans;
}
int main()
{
cin>>n>>m;
pos(i,1,n) {cin>>a[i];add(i,a[i]-a[i-1]);}
pos(i,1,m)
{
int x,l,r,k;
cin>>x;
if(x==1)
{
cin>>l>>r>>k;
add(l,k),add(r+1,-k);
}
else
{
cin>>k;
cout<<sum(k)<<endl;
}
}
return 0;
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
3.差分实现区间改/区间查
\[sum[i]=\sum_{j=1}^i c[j] \times(i-j+1)
\\
sum[i]=(i+1) \times \sum_{j=1}^i c[j] -\sum_{j=1}^i c[j] \times j
\]
int n,m;
int d1[Max],d2[Max],a[Max],b[Max];
int lowbit(int x){return x&-x;}
inline void add(int *c,int p,int k)
{
while(p<=n){c[p]+=k;p+=lowbit(p);}
}
inline int sum(int *c,int p)
{
int ans=0;
while(p){ans+=c[p];p-=lowbit(p);}
return ans;
}
inline int f(int x)
{
return b[x]+(x+1)*sum(d1,x)-sum(d2,x);
}
int main()
{
cin>>n>>m;
pos(i,1,n)
{
cin>>a[i];
b[i]=b[i-1]+a[i];
}
pos(i,1,m)
{
int x,l,r,k;
cin>>x>>l>>r;
if(x==1)
{
cin>>k;
add(d1,l,k),add(d1,r+1,-k),add(d2,l,k*l),add(d2,r+1,-k*(r+1));
}
else cout<<f(r)-f(l-1)<<endl;
}
return 0;
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
4.最值
int m,n;
int a[Max],c[Max],MAX[Max];
char ch;
inline int lowbit(int x){return x&-x;}
void add(int p,int k)
{
a[p]=k;
while(p<=n)
{
c[p]=max(c[p],k);
int t=lowbit(p);
for(int i=1;i<t;i*=2) c[p]=max(c[p],c[p-i]);
p+=lowbit(p);
}
}
int query(int l,int r)
{
int ans=0;
while(1)
{
ans=max(ans,a[r]);
if(r==l) break;
for(r-=1;r-l>=lowbit(r);r-=lowbit(r)) ans=max(ans,c[r]);
}
return ans;
}
signed main()
{
cin>>n>>m;
pos(i,1,n) cin>>a[i];
pos(i,1,n) add(i,a[i]);
int y,x;
pos(i,1,m)
{
ch=getchar();
while(ch<'A'||ch>'Z') ch=getchar();
scanf("%lld%lld",&x,&y);
if(ch=='Q') cout<<query(x,y)<<endl;
else
{
if(y<=a[x]) continue;
add(x,y);
}
}
return 0;
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
线段树
#define mid (s+((t-s)>>1))
#define ls (p<<1)
#define rs ((p<<1)|1)
\(\\\)
\(\\\)
以下代码中
\(s,t\)代表当前区间
\(l,r\)代表询问区间
\(\\\)
\(\\\)
区间修改,区间查询
int n,m;
int a[Max],d[Max*4],b[Max*4];
void pushup(int p)
{
d[p]=d[ls]+d[rs];
}
void pushdown(int s,int t,int p)
{
if(b[p]!=0)
{
b[ls]+=b[p],b[rs]+=b[p];
d[ls]+=b[p]*(mid+1-s);
d[rs]+=b[p]*(t-mid);
b[p]=0;
}
return;
}
void build(int s,int t,int p)
{
if(s==t)
{
d[p]=a[s];
return;
}
build(s,mid,ls);
build(mid+1,t,rs);
pushup(p);
}
int query(int l,int r,int s,int t,int p)
{
if(l<=s&&t<=r)
{
return d[p];
}
int sum=0;
pushdown(s,t,p);
if(l<=mid) sum+=query(l,r,s,mid,ls);
if(r>mid) sum+=query(l,r,mid+1,t,rs);
return sum;
}
void update(int l,int r,int s,int t,int p,int c)
{
if(l<=s&&t<=r)
{
d[p]+=(t-s+1)*c;
b[p]+=c;
return;
}
pushdown(s,t,p);
if(l<=mid) update(l,r,s,mid,ls,c);
if(r>mid) update(l,r,mid+1,t,rs,c);
pushup(p);
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
单点修改,区间查询
int n,m;
int a[Max],d[Max*4];
void pushup(int p)
{
d[p]=d[ls]+d[rs];
}
void build(int s,int t,int p)
{
if(s==t)
{
d[p]=a[s];
return;
}
build(s,mid,ls);
build(mid+1,t,rs);
pushup(p);
}
int query(int l,int r,int s,int t,int p)
{
if(l<=s&&t<=r)
{
return d[p];
}
int sum=0;
// pushdown(s,t,p);
if(l<=mid) sum+=query(l,r,s,mid,ls);
if(r>mid) sum+=query(l,r,mid+1,t,rs);
return sum;
}
void update(int x,int s,int t,int p,int c)
{
if(s==t)
{
d[p]+=c;
return;
}
// pushdown(s,t,p);
if(x<=mid) update(x,s,mid,ls,c);
if(x>mid) update(x,mid+1,t,rs,c);
pushup(p);
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
单点查询,区间修改
int n,m;
int a[Max],d[Max*4],b[Max*4];
void pushup(int p)
{
d[p]=d[ls]+d[rs];
}
void pushdown(int s,int t,int p)
{
if(b[p]!=0)
{
b[ls]+=b[p],b[rs]+=b[p];
d[ls]+=b[p]*(mid+1-s);
d[rs]+=b[p]*(t-mid);
b[p]=0;
}
return;
}
void build(int s,int t,int p)
{
if(s==t)
{
d[p]=a[s];
return;
}
build(s,mid,ls);
build(mid+1,t,rs);
pushup(p);
}
int query(int x,int s,int t,int p)
{
if(s==t)
{
return d[p];
}
pushdown(s,t,p);
if(x<=mid) return query(x,s,mid,ls);
if(x>mid) return query(x,mid+1,t,rs);
}
void update(int l,int r,int s,int t,int p,int c)
{
if(l<=s&&t<=r)
{
d[p]+=c*(t-s+1);
b[p]+=c;
return;
}
pushdown(s,t,p);
if(l<=mid) update(l,r,s,mid,ls,c);
if(r>mid) update(l,r,mid+1,t,rs,c);
pushup(p);
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
主席树
\(\\\)
\(\\\)
1
int cnt,n,m;
int a[Max],root[Max];
struct Tree
{
int l,r,val;
}tree[Max];
int clone(int p)
{
cnt++;
tree[cnt]=tree[p];
return cnt;
}
int build(int p,int s,int t)
{
p=++cnt;
if(s==t)
{
tree[cnt].val=a[s];
return p;
}
tree[p].l=build(tree[p].l,s,mid);
tree[p].r=build(tree[p].r,mid+1,t);
return p;
}
int update(int p,int s,int t,int x,int v)
{
p=clone(p);
if(s==t)
{
tree[p].val=v;
return p;
}
if(x<=mid) tree[p].l=update(tree[p].l,s,mid,x,v);
if(x>mid) tree[p].r=update(tree[p].r,mid+1,t,x,v);
return p;
}
int query(int p,int s,int t,int x)
{
if(s==t) return tree[p].val;
if(x<=mid) return query(tree[p].l,s,mid,x);
else return query(tree[p].r,mid+1,t,x);
}
signed main()
{
cin>>n>>m;
pos(i,1,n) cin>>a[i];
root[0]=build(0,1,n);
return 0;
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
区间第k小
int clone(int p)
{
cnt++;
tree[cnt]=tree[p];
tree[cnt].val++;
return cnt;
}
int build(int p,int s,int t)
{
p=++cnt;
if(s==t)
{
// tree[cnt].val=a[s];
return p;
}
tree[p].l=build(tree[p].l,s,mid);
tree[p].r=build(tree[p].r,mid+1,t);
return p;
}
int update(int p,int s,int t,int x,int v)
{
p=clone(p);
if(s==t)
{
// tree[p].val+=v;
return p;
}
if(x<=mid) tree[p].l=update(tree[p].l,s,mid,x,v);
if(x>mid) tree[p].r=update(tree[p].r,mid+1,t,x,v);
return p;
}
int query1(int p,int q,int s,int t,int k)
{
int x=tree[tree[p].l].val-tree[tree[q].l].val;
if(s==t) return b[s];
if(x>=k) return query1(tree[p].l,tree[q].l,s,mid,k);
else return query1(tree[p].r,tree[q].r,mid+1,t,k-x);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+1+n);
int nn=unique(b+1,b+1+n)-b-1;
rt[0]=build(0,1,nn);
for(int i=1;i<=n;i++)
{
int x=lower_bound(b+1,b+1+nn,a[i])-b;
rt[i]=update(rt[i-1],1,nn,x,1);
}
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
cout<<query1(rt[y],rt[x-1],1,nn,z)<<"\n";
}
return 0;
}