zoukankan      html  css  js  c++  java
  • POJ

    刚开始学习线段树,再次以本题为例,做点笔记

    题意:题目有两种操作,一种是询问[l,r]区间的和,另一种是[l,r]区间上的每一位数都加上C

    分析:显然,直接将数字C加到区间上的每一位数上比较耗时,效率也比较低,所以我们要另辟蹊径,那就是lazy操作。

      lazy操作的意思就是先不将[l,r]区间的数上都加上C,也就是不直接将树的根的每一数+C,而是将+C这个标记推到他的两个子节点上,并将子节点更新sum[rt<<1]+=(tree[rt<<1].r-tree[rt<<1].l+1)*C(右节点同理),add[rt<<1]+=add[rt],add[rt]=0;这样做的话,只有这个区间被用到的时候,才会去用这个区间的子区间来更新他自己的区间和,大大的提高了效率

    //pushdown
    void pushdown(int rt){
    	if(add[rt]){
    		add[rt<<1]+=add[rt];
    		add[rt<<1|1]+=add[rt];
    		sum[rt<<1]+=1LL*(tree[rt<<1].r-tree[rt<<1].l+1)*add[rt];
    		sum[rt<<1|1]+=1LL*(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*add[rt];
    		add[rt]=0;
    	}
    }
    

      因为做了lazy操作,所以本个节点被使用时,才会被更新节点信息,所以在进行query时,必须使用pushdown函数,来下推标记

      下面是个人代码

    #define debug
    #include<stdio.h>
    #include<math.h>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<string>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<functional>
    #include<iomanip>
    #include<map>
    #include<set>
    #define pb push_back
    #define dbg(x) cout<<#x<<" = "<<(x)<<endl;
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef pair<ll,ll>PLL;
    typedef pair<int,ll>Pil;
    const ll INF = 0x3f3f3f3f;
    const double inf=1e8+100;
    const double eps=1e-8;
    const int maxn =1e6;
    const int N = 510;
    const ll mod=1e9+7;
    //------
    //define
    struct node{
    	int l,r;
    }tree[maxn<<2];
    ll sum[maxn<<2],add[maxn<<2];
    //pushup
    void pushup(int rt) {
    	sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 
    }
    //pushdown
    void pushdown(int rt){
    	if(add[rt]){
    		add[rt<<1]+=add[rt];
    		add[rt<<1|1]+=add[rt];
    		sum[rt<<1]+=1LL*(tree[rt<<1].r-tree[rt<<1].l+1)*add[rt];
    		sum[rt<<1|1]+=1LL*(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*add[rt];
    		add[rt]=0;
    	}
    }
    //buildtree
    void build(int l,int r,int rt) {
    	tree[rt].l=l;
    	tree[rt].r=r;
    	add[rt]=0;
    	if(l==r) {
    		//gra[rt]=a[l];
    		scanf("%lld",&sum[rt]);
    		return;
    	}
    	int m=l+r>>1;
    	build(l,m,rt<<1);
    	build(m+1,r,rt<<1|1);
    	pushup(rt);
    }
    //update
    void update(int L,int R,int C,int rt){
    	if(tree[rt].l==L&&tree[rt].r==R){
    		add[rt]+=C;
    		sum[rt]+=1ll*C*(R-L+1);
    		return;
    	}
    	if(tree[rt].l==tree[rt].r)return;
    	pushdown(rt);
    	int m=tree[rt].l+tree[rt].r>>1;
    	if(R<=m){
    		update(L,R,C,rt<<1);
    	}else if(L>m){
    		update(L,R,C,rt<<1|1);
    	}else{
    		update(L,m,C,rt<<1);
    		update(m+1,R,C,rt<<1|1);
    	}
    	pushup(rt);
    }
    //query
    ll query(int L,int R,int rt) {
    	if(L==tree[rt].l&&R==tree[rt].r){
    		return sum[rt];
    	}
    	pushdown(rt);
    	ll ans=0;
    	int m=tree[rt].l+tree[rt].r>>1;
    	if(R<=m){
    		ans+=query(L,R,rt<<1);
    	}else if(L>m){
    		ans+=query(L,R,rt<<1|1);
    	}else{
    		ans+=query(L,m,rt<<1);
    		ans+=query(m+1,R,rt<<1|1);
    	}
    	return ans;
    }
    //solve
    void solve() {
    	int n,t;
    	while(~scanf("%d%d",&n,&t)){
    		build(1,n,1);
    		while(t--){
    			char mark[2];
    			int A,B,C;
    			scanf("%s",&mark);
    			if(mark[0]=='Q'){
    				scanf("%d%d",&A,&B);
    				printf("%lld
    ",query(A,B,1));
    			}else{
    				scanf("%d%d%d",&A,&B,&C);
    				update(A,B,C,1);
    			}
    		}
    	}
    }
    //main
    int main() {
    //	ios_base::sync_with_stdio(false);
    #ifdef debug
    	freopen("in.txt", "r", stdin);
    //	freopen("out.txt","w",stdout);
    #endif
    //	cin.tie(0);
    //	cout.tie(0);
    	solve();
    	/*
    		#ifdef debug
    			fclose(stdin);
    			fclose(stdout);
    			system("out.txt");
    		#endif
    	*/
    	return 0;
    }
    

      

  • 相关阅读:
    [背包问题][二进制优化] Jzoj P4224 食物
    [并查集][排序] Jzoj P4223 旅游
    [哈夫曼树][优先队列] Bzoj P4198 荷马史诗
    [hash][差分][虚树] Jzoj P6011 天天爱跑步
    [dp] Jzoj P6012 荷马史诗
    [dp][递归] Jzoj P4211 送你一棵圣诞树
    [数学] Jzoj P3912 超氧化钾
    堆学习笔记(未完待续)(洛谷p1090合并果子)
    [AC自动机]luogu P2444 病毒
    [概率期望][DP]luogu P3830 随机树
  • 原文地址:https://www.cnblogs.com/visualVK/p/8964802.html
Copyright © 2011-2022 走看看