线段树(java)

1.相关时间复杂度:
因为总结点个数为2n,因此:
初始化:O(n)
因为不论哪种操作,对于每个深度都最多访问常数个结点,因此:
每次更新:O(logn)
每次求值:O(logn)
2.线段树结构:
线段树结点下标和元素范围下标均从1记。那么:
每个结点存着[l,r]范围内的值。
第1个结点维护[1,n]范围的值。
每个结点k的左右叶子结点下标分别为k<<1,k<<1|1。
然而初始数组的下标是从0记的,所以在build的时候,c[k].sum=s[l-1]。
c[i].l和c[i].r记录了该结点维护的元素的范围下标。

维护区间和板子(单点更新,区间查询)。

public class Main {
	static InputReader sc=new InputReader(System.in);
	static PrintWriter out=new PrintWriter(System.out);
	static int mod=1000000007,n,maxn=100010,INF=1000000000;
	static SegmentTree t=new SegmentTree();
	static char s[];
	static class tnode{
		int l,r;
		long sum;
	}
	static class SegmentTree{
		tnode c[]=new tnode[maxn*4];
		SegmentTree() {
			for(int i=0;i<4*maxn;i++) {
				c[i]=new tnode();
			}
		}
		void build(int l,int r,int k) {
		//tnode存了其维护的区间.所以只在build中需要lr参数,update query不需要。
			c[k].l=l;
			c[k].r=r;
			c[k].sum=0;
			if(l==r) {
				c[k].sum=s[l-1];
				return;
			}
			int mid=(l+r)/2;
			build(l,mid,k<<1);
			build(mid+1,r,k<<1|1);
			c[k].sum=c[k<<1].sum+c[k<<1|1].sum;
			c[k].sum=(c[k].sum+mod)%mod;
		}
		void update(int ind,int k,int p) {
		//ind为原数组中第Ind,k为当前所在线段树结点的下标,p为修改后的值
			if(c[k].l==c[k].r) {
				c[k].sum=p;
				return;
			}
			int mid=c[k].l+c[k].r;
			mid/=2;
			if(ind<=mid) update(ind,k<<1,p);
			else update(ind,k<<1|1,p);
			c[k].sum=c[k<<1].sum+c[k<<1|1].sum;
			c[k].sum=(c[k].sum+mod)%mod;
		}
		int query(int a,int b,int k) {//查询的区间[a,b],线段树结点下标k
			if(c[k].l>=a&&c[k].r<=b) {
				return c[k].val;
			}
			int mid=c[k].l+c[k].r;
			mid/=2;
			int L=0,R=0;
			if(a<=mid)L=query(a,b,k<<1);
			if(b>mid)R=query(a,b,k<<1|1);
			return L+R;
		}
	}
	public static void main(String args[]) {
		n=sc.nextInt();
		s=sc.nextLine().toCharArray();
		t.build(1, n, 1);
	}
}

结点维护其区间的和,区间更新区间查询,旧lazytag的更新只在查询时操作,更新函数只负责将lazytag累加和更新对应结点的值并pushup.(这个没写pushup pushdown函数,可以写= =)
注:lazytag只在区间更新中有意义,单点更新不需要lazytag

public class C {
	public static int INF=(1<<30)-1,maxn=100100,n;
	public static long arr[]=new long[maxn*4],tree[]=new long[maxn*4],add[]=new long[maxn*4];
	public static long build(int l,int r,int rt) {
		if(l==r) {
			tree[rt]=arr[l];
			return tree[rt];
		}
		int mid=(l+r)/2;
		long L=build(l,mid,2*rt);
		long R=build(mid+1,r,2*rt+1);
		tree[rt]=L+R;
		return tree[rt];
	}
	public static long update(int a,int b,int k,int l,int r,int rt) {
		if(a<=l&&b>=r) {
			add[rt]+=k;
			return (r-l+1)*k;
		}
		int mid=(l+r)/2;
		int ans=0;
		if(a<=mid) {
			ans+=update(a,b,k,l,mid,rt*2);
		}
		if(b>=mid+1) {
			ans+=update(a,b,k,mid+1,r,rt*2+1);
		}
		tree[rt]+=ans;
		return ans;
	}
	public static long query(int a,int b,int l,int r,int rt) {
		tree[rt]+=(r-l+1)*add[rt];
        if(l!=r){
            add[rt*2]+=add[rt];
            add[rt*2+1]+=add[rt];
        }
        add[rt]=0;
		if(a<=l&&b>=r) {
			return tree[rt];
		}
		int mid=(l+r)/2;
		long ans=0;
		if(a<=mid) {
			ans+=query(a,b,l,mid,2*rt);
		}
		if(b>=mid+1) {
			ans+=query(a,b,mid+1,r,2*rt+1);
		}
		return ans;
	}
	public static InputReader sc=new InputReader(System.in);
	public static void main(String args[]) {
		n=sc.nextInt();
		int N=n;
		n=1;
		while(n<N) {
			n*=2;
		}
		int q=sc.nextInt();
		for(int i=1;i<=N;i++) {
			arr[i]=sc.nextLong();
			//System.out.println(arr[i]);
		}
		build(1,n,1);
		while(q-->0) {
			String str;
			str=sc.readString();
			if(str.charAt(0)=='Q') {
				int l=sc.nextInt();
				int r=sc.nextInt();
				System.out.println(query(l, r, 1, n, 1));
			}else {
				int l=sc.nextInt();
				int r=sc.nextInt();
				int c=sc.nextInt();
				update(l, r, c, 1, n, 1);
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值