小技巧之差分

今天复习了下差分,发现还没写过差分的博客,便来写博客氵时间了.。
差分是啥不用多bb了,直接看简单用途吧。
差分思想的用途
差分数组适用于离线的区间修改问题,如果是在线,应该用线段树或其他数据结构。
(1)可以快速处理区间加减操作,并询问操作结束的每个元素的最新值。
(2)可以快速处理多次询问区间和问题。
利用差分数组求出M次处理后数组a[]每个元素的值,然后用O(N)的复杂度求出数组
a[]每个位置的前缀和sum[i],则区间[L,R]的和ans为sum[R]-sum[L-1]。
然后我知道的差分就三种,大体列一下吧。
一维数组数组差分
code:

for(int i=1;i<=n;i++) cin>>a[i]; //读入原始数据  
while(m--) 
{ 
    int L,R,V; 
    cin>>L>>R>>V; 
    b[L]+=V; 
    b[R+1]-=V; 
} 
for(int i=1;i<=n;i++) 
{ 
  b[i]+=b[i-1];   //前缀和  
  a[i]+=b[i];     //合并  
} 
for(int i=1;i<=n;i++) cout<<a[i]<<" ";  //输出操作后的结
cout<<endl; 
return 0; 

二维数组差分
code:

    for (i=1; i<=n; i++) {
        for (j=1; j<=m; j++) {
            scanf("%d", &a[i][j]);
            diff[i][j] = a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
        }
    }
 
    for (i=0; i<q; i++) {
        int x1, y1, x2, y2, c;
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
        diff[x1][y1] += c;
        diff[x1][y2+1] -=c;
        diff[x2+1][y1] -=c;
        diff[x2+1][y2+1] += c;
    }
 
    for (i=1; i<=n; i++) {
        for (j=1; j<=m; j++) {
            diff[i][j] += diff[i-1][j]+diff[i][j-1]-diff[i-1][j-1];
            printf("%d ", diff[i][j]);
        }
        printf("\n");
    }
 
    return 0;

树上差分
树上差分呢则要分为两种,一是权值在点上
code:

for(int i=1;i<=m;i++)
{
	x=Read(),y=Read();
	val[x]+=1,val[y]+=1;
	int saber=lca(x,y);
	val[saber]-=1;
	val[f[saber][0]]-=1;
}
	
void Find(int u,int fa)
{
 	for(int i=first[u];i;i=Next[i])
	{
		int v=to[i];
		if(v==fa) continue;
		Find(v,u);
		val[u]+=val[v];
	}
}

而当权值在边上时,我们则选择以每条边两端深度较大的节点存储该边的差分数组,只不过跟点差分有点区别

diff[u]+=x,diff[v]+=x,diff[o]-=2*x;//o是lca

其余都差不多。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值