第五讲 树状数组与线段树 未完结

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树状数组与线段树

树状数组和线段树有啥区别?

菜鸡2014X的数据结构学习小结:线段树与树状数组

树状数组和线段树的那些事

树状数组与线段树

树状数组与线段树