第五讲 树状数组与线段树 未完结
Posted 辉小歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第五讲 树状数组与线段树 未完结相关的知识,希望对你有一定的参考价值。
目录
1264. 动态求连续区间和 【树状数组板子题】
树状数组解法:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N],tr[N];
int lowbit(int x)
{
return x & -x;
}
void add(int x,int v)
{
for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=v;
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) add(i,a[i]);
while(m--)
{
int k,x,y;
scanf("%d%d%d",&k,&x,&y);
if(k==0) printf("%d\\n",query(y)-query(x-1));
else add(x,y);
}
return 0;
}
线段树写法:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
int w[N];
struct Node
{
int l,r;
int sum;
}tr[N*4];
void pushup(int u)
{
tr[u].sum=tr[u<<1].sum+tr[u<<1 | 1].sum;
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,w[r]};
else
{
tr[u]={l,r};
int mid=(l+r)>>1;
build(u<<1,l,mid),build(u<<1 | 1,mid+1,r);
pushup(u);
}
}
int query(int u,int l,int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
int mid=(tr[u].l+tr[u].r)>>1;
int sum=0;
if(l<=mid) sum=query(u<<1,l,r);
if(r>mid) sum+=query(u<<1 | 1,l,r);
return sum;
}
void modify(int u,int x,int v)
{
if(tr[u].l==tr[u].r) tr[u].sum+=v;
else
{
int mid=(tr[u].l+tr[u].r)>>1;
if(x<=mid) modify(u<<1,x,v);
else modify(u<<1 | 1,x,v);
pushup(u);
}
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>w[i];
build(1,1,n);
int k,a,b;
while(m--)
{
cin>>k>>a>>b;
if(k==0) printf("%d\\n",query(1,a,b));
else modify(1,a,b);
}
return 0;
}
1265. 数星星 【树状数组变种】
#include<bits/stdc++.h>
using namespace std;
const int N=32005;
int tr[N],n,st[N];
int lowbit(int x)
{
return x & -x;
}
void add(int x)
{
for(int i=x;i<N;i+=lowbit(i)) tr[i]++;
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
int main(void)
{
cin>>n;
for(int i=0;i<n;i++)
{
int x,y; cin>>x>>y;
x++;
st[query(x)-query(0)]++;
add(x);
}
for(int i=0;i<n;i++) cout<<st[i]<<endl;
return 0;
}
1270. 数列区间最大值 【线段树 / 区间内求最大值】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
int w[N];
struct Node
{
int l,r;
int sum;
}tr[N*4];
void pushup(int u)
{
tr[u].sum=max(tr[u<<1].sum,tr[u<<1 | 1].sum);
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,w[r]};
else
{
tr[u]={l,r};
int mid=(l+r)>>1;
build(u<<1,l,mid),build(u<<1 | 1,mid+1,r);
pushup(u);
}
}
int query(int u,int l,int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
int mid=(tr[u].l+tr[u].r)>>1;
int sum=0;
if(l<=mid) sum=query(u<<1,l,r);
if(r>mid) sum=max(sum,query(u<<1 | 1,l,r));
return sum;
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
build(1,1,n);
int a,b;
while(m--)
{
scanf("%d%d",&a,&b);
printf("%d\\n",query(1,a,b));
}
return 0;
}
1215. 小朋友排队 【树状数组】
每个数所对应的换位次数(逆序对)=前面比它大的+后面比它小的
树状数组维护的是每一个身高所对应的个数
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e6+10;
int n;
int h[N],tr[N];
int sum[N];
int lowbit(int x)
{
return x&-x;
}
void add(int x,int v)
{
for(int i=x;i<N;i+=lowbit(i)) tr[i]+=v;
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
int main(void)
{
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&h[i]),h[i]++;
for(int i=0;i<n;i++)
{
sum[i]=query(N-1)-query(h[i]);
add(h[i],1);
}
memset(tr,0,sizeof tr);
for(int i=n-1;i>=0;i--)
{
sum[i]+=query(h[i]-1);
add(h[i],1);
}
LL res=0;
for(int i=0;i<n;i++) res+=sum[i]*(sum[i]+1ll)/2;
cout<<res;
return 0;
}
AcWing 1228. 油漆面积 【不会 扫描线】
AcWing 1232. 三体攻击 【不会 三维差分】
AcWing 1237. 螺旋折线 【找规律】
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int x;
int y;
long long ans;
int main(void)
{
cin>>x>>y;
if(abs(x)<=y&&y>=0)//上
{
if(x>=0)
ans=(long long)(2*y)*(2*y)-(y-x);
else
ans=(long long)(2*y)*(2*y-1)+(y-abs(x));
}
if(abs(y)<=x&&x>=0)//左
{
if(y>=0)
ans=(long long)(2*x)*(2*x)+(x-y);
else
ans=(long long)(2*x)*(2*x+1)-(x-abs(y));
}
if(abs(x)<=abs(y)+1&&y<0)//下
{
if(x>=0)
ans=(long long)(2*abs(y))*(2*abs(y)+1)+(abs(y)-x);
else
ans=(long long)(2*(abs(y)+1)-1)*(2*(abs(y)+1)-1)-(abs(y)+1-abs(x));
}
if(abs(y)<=abs(x)-1&&x<0)//右
{
if(y>=0)
ans=(long long)(2*abs(x))*(2*abs(x)-1)-(abs(x树状数组与线段树