个人ACM入门每周小总结④(背包,树状数组,线段树)

简单背包问题

01背包

    scanf("%d%d", &n, &m);  n种,限制最大m
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &w, &v);  重w,价值v
		for (int j = m; j >= w; j--) {  从后向前遍历
			dp[j] = std::max(dp[j], dp[j - w] + v);
		}
	}

 01背包中物品只能取一次,从后向前遍历时的dp是上一个物品遍历后造成影响,而该物品的遍历未造成影响的

完全背包

for (int i = 1 ; i <= n ; i++) {
        scanf("%d%d", &w, &v);
		for (int j = w ; j <= m ; j++) {  从前向后遍历
			dp[j] = std::min(dp[j], dp[j - w] + v);
		}
	}

完全背包中物品能取无数次,从前向后遍历时的dp是上一个物品和该物品的遍历均造成影响的 

多重背包

        for(int j=1;j<=n;j<<=1){ 二进制压缩,转换为01背包
			++cnt;
			b[cnt].h=h*j;
			b[cnt].l=l;
			n-=j;
		}
		if(n){
			++cnt;
			b[cnt].h=h*n;
			b[cnt].l=l;
		}

树状数组

 适用范围:

1.单点修改,单点查询

2.区间修改,单点查询

3.区间查询,区间修改

单点修改,区间查询 

inline int lowbit(int x) {
	return x & -x;
}
void update(int x,int k,int n)
{
	for(int i=x;i<=n;i+=lowbit(i))
	t[i]+=k;
}
int getsum(x){
	int sum = 0;
	for(int i=x;i;i-=lowbit(i)){
		sum+=t[i];
	}
	return sum;
}

区间修改,单点查询
利用差分数组的性质,其前缀和即为该元素本身

update(l, x, n);
update(r + 1, -x, n);

区间修改,区间查询

构造差分数组sum1 [ n ], sum2 = sum1 [ i ] * i;( i 从1开始计数)

void update(ll p, ll x){
    for(int i = p; i <= n; i += i & -i)
        sum1[i] += x, sum2[i] += x * p;
}
void range_update(ll l, ll r, ll x){
    update(l, x), update(r + 1, -x);
}
ll getsum(ll p){
    ll res = 0;
    for(int i = p; i; i -= i & -i)
        res += (p + 1) * sum1[i] - sum2[i]; 重点!
    return res;
}
ll range_getsum(ll l, ll r){
    return getsum(r) - getsum(l - 1);
}

树状数组 数据结构详解与模板(可能是最详细的了)_bestsort的博客-CSDN博客_树状数组

线段树

 线段树 从入门到进阶(超清晰,简单易懂)_繁凡さん的博客-CSDN博客_线段树

进阶算法,暂时搁置先推紫书去了,结束之后才觉得暑期集训如此短暂,ACM之路道阻且长

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值