線段樹動態開點


其實在tzt版線段樹的基礎上稍微加一些東西就好了。我們不預先開點,每當需要用到一個點時,我們才開。空間復雜度可以優化到 m(查詢)log n。

code(線段樹1,其實這道題用動態開點沒啥意義沒啥意義,當作練習)

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include <stack>
#include<vector>
#define half (l+r)>>1;
using namespace std;
int n,m;
const int maxn=400000;
struct hzw
{
	int sum;
	int add;
	int lc;
	int rc;  
}t[maxn];
int a[maxn],tot;
inline void update(int &s,int l,int r,int cl,int cr,int x)
{
	if (!s) s=++tot;
    t[s].sum+=(cr-cl+1)*x;
    if (l==cl&&r==cr)
    {
    	t[s].add+=x;
    	return ;
    }
    int mid=half;
    if (cr<=mid)     update(t[s].lc,l,mid,cl,cr,x);
	else if (cl>mid) update(t[s].rc,mid+1,r,cl,cr,x);
	else {
		update(t[s].lc,l,mid,cl,mid,x);
		update(t[s].rc,mid+1,r,mid+1,cr,x);
	}
}
inline int query(int s,int l,int r,int cl,int cr,int cnt)
{
	if (!s) return 0;
	if (l==cl&&r==cr)
	{
		return cnt*(cr-cl+1)+t[s].sum;
	}
	int mid=half;
	if (cr<=mid)     return query(t[s].lc,l,mid,cl,cr,cnt+t[s].add);
	else if (cl>mid) return query(t[s].rc,mid+1,r,cl,cr,cnt+t[s].add);
	else {
		return query(t[s].lc,l,mid,cl,mid,t[s].add+cnt)+query(t[s].rc,mid+1,r,mid+1,cr,cnt+t[s].add);
	}
}
int main() {
	int ans=0,cur;
  	tot++;
  	cin>>n>>m;
  	int root=1; 
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for (int i=1;i<=n;++i) update(root,1,n,i,i,a[i]);
	for(int i=1,q,x,y;i<=m;i++)
	{   
		scanf("%d%d%d",&q,&x,&y);
		if(q==1)
		{	scanf("%d",&cur);
			update(root,1,n,x,y,cur);
		}
		else
		{	
			cout<<query(1,1,n,x,y,0)<<endl;
		}
	}
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM