差分在ACM竞赛中的应用

差分在ACM竞赛中的应用

众所周知,前缀和是差是原序列,差分的合适原序列
B是A的差分数组
B [ 1 ] = A [ 1 ] , B [ i ] = A [ i ] − A [ i − 1 ] ( 2 &lt; = i &lt; = n ) B[1] = A[1],B[i] = A[i]-A[i-1](2&lt;=i&lt;=n) B[1]=A[1],B[i]=A[i]A[i1](2<=i<=n)

1 一维差分

0304 IncDec Sequence
0304 IncDec Sequence
给定一个长度为 n ( n ≤ 1 0 5 ) n(n≤10^5 ) n(n105)的数列 a 1 , a 2 , … , a n {a_1,a_2,…,a_n} a1,a2,,an,每次可以选择一个区间 [ l , r ] [l,r] [l,r],使下标在这个区间内的数都加一或者都减一。
求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。

const int maxn = 1e5+10;
LL a[maxn],b[maxn];
int main(void)
{
    int n;cin>>n;
    for(int i = 1;i <= n ;++i)
        scanf("%lld",&a[i]);
    for(int i = 1;i <= n; ++i)
        b[i] = a[i]-a[i-1];
    LL sum1,sum2;
    sum1 = sum2 = 0;   
    for(int i = 2;i <= n; ++i)
        if(b[i] > 0)
            sum1 += b[i];
        else
            sum2 += abs(b[i]);
    cout<<max(sum1,sum2)<<endl;
    cout<<abs(sum1-sum2)+1<<endl;
    

   return 0;
}


2 二维差分

hdu6514

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;


LL mat[10000007];
int r, c;
int n, q;

inline void m(int x, int y,int p) {
     if(x < 0 || x >= r || y < 0 ||y >= c) return ;
//     cout<<x*c+y<<endl;
     mat[x*c+y] += p;
}
void solve(int t) {
    for (int i= 0; i<r; ++i) {
        for (int j= 0; j< c; ++j) {
            if(t&&mat[i*c+j])
                mat[i*c+j] = 1; 
            if(i)
                mat[i*c+j] += mat[(i-1)*c+j];
            if(j)
                mat[i*c+j] += mat[i*c+(j-1)];
            if(i&&j)
                mat[i*c+j] -= mat[(i-1)*c+(j-1)]; 
        }
    }
}

int main() {
//    ios::sync_with_stdio(0);
    while(~scanf("%d%d",&r,&c)) {
        memset(mat,0,sizeof(mat));
//        cout<<r<<" "<<c<<endl;
        int x1,y1,x2,y2;
        int n;scanf("%d",&n);
        for (int i=0; i<n; ++i) {
//            cin >> x1>>y1>>x2>>y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1--,y1--,x2--,y2--;
//            cout<<x1<<" "<<y1<<" "<<x2<< " "<<y2<<endl; 
            m(x1,y1,1);
            m(x2+1,y1,-1);
            m(x1,y2+1,-1);
            m(x2+1,y2+1,1);
        }
//        cout<<mat[7]<<endl;
//           for(int i = 0;i < r; ++i,cout<<endl)
//            for(int j = 0;j < c; ++j) 
//                cout<<mat[i*c+j]<<" ";
//            cout<<endl;
        solve(0);
        

        solve(1);
//              for(int i = 0;i < r; ++i,cout<<endl)
//            for(int j = 0;j < c; ++j) 
//                cout<<mat[i*c+j]<<" ";
        int q;scanf("%d",&q);
        while(q--){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1--,y1--,x2--,y2--;
            LL sum = mat[x2*c+y2],sum1 = x2*c+y2;
//            LL sum1 = 0;
            sum1 = (x2-x1+1)*(y2-y1+1);
            if(x1)
                sum -= mat[(x1-1)*c+y2];//,sum1 -= (x1-1)*c+y2;
            if(y1)
                sum -= mat[x2*c+y1-1];//,sum1 -= x2*c+y1-1;
            if(x1&&y1)
                sum += mat[(x1-1)*c+(y1-1)];//,sum1 += (x1-1)*c+y1-1;
//            cout<<sum<<endl;    
//            cout<<sum<<endl;
//            cout<<sum1<<endl;
            puts(sum==sum1?"YES":"NO");
                
        }
    }
    
    
    return 0;
}

3 树上差分

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值