二重差分

题目链接


题目大意:

小明在游戏中搭建了一堵长为的城墙,墙上有个支撑点。为了知道墙是否足够坚固,小明喊来他的好朋友小刚帮助他进行测试。
小刚有一种特殊的炮弹可以对墙上任意一个支撑点进行轰击,收到轰击的支撑点将受到点伤害,此外,炮弹还会对个支撑点造成溅射伤害(受到的伤害依次减1)。
现在知道每个支撑点能够承受的最大伤害,1<=n,m<=2^5当时视为该支撑点已经完全损坏。小刚一共进行轮炮击,在炮击结束之后请你计算出一共有多少个支撑点被完全损坏。

题目思路:

\(~~\)我们通过写两组样例来观察每次造成伤害的效果

10 2
10 10 10 10 10 10 10 10 10 10
5 4
1 10

第一次我们对第五个点造成4点伤害,同时对周围造成溅射伤害:

1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 3 2 1 0 0

我们发现每次伤害的变化的间隔都是相同的,我们就考虑能不能优化存储这种变化,于是就先考虑能不能对其进行差分,最后通过前缀和来计算对某个点的伤害
于是我们得到第一次差分后的结果:

1 2 3 4 5 6 7 8 9 10
0 1 1 1 1 -1 -1 -1 -1 0

我们惊奇的发现第一次差分后的结果依然是一种间隔相同的变化,那这就意味着可以进行第二次差分:

1 2 3 4 5 6 7 8 9 10
0 1 0 0 0 -1 -1 0 0 0 1

经过这样的变化之后我们发现二次差分后的结果更便于处理:get新技能
只需要简单的处理二次差分的伤害,最后通过两次前缀和就可以求出某一点最终受到的伤害值


代码实现

# include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5+10;
int a[N];
int b[N],c[N];
int t[N];
signed main(){
    int n,m;
    cin>>n>>m;
    for(int i = 1;i <= n;++i){
        cin>>a[i];
    }
    for(int i = 1;i <= n;++i) b[i] =a[i]- a[i-1];
    for(int i = 1;i <= n;++i) c[i] = b[i]- b[i-1];
    while(m--){
        int p,x;
        cin>>p>>x;
        if(x == 1){
            c[p] -= 1;
            c[p+1] +=1;
            c[p+1] += 1;
            c[p+2] -= 1;
            continue;
        }
        if(p-x+1>=1){
            c[p-x+1] -= 1;
            c[p+1] +=1;
        }
        else if(p == 1){
            c[p] -= x;
            c[p+1] +=x;
        }
        else{
            int t = x-(p-1);
            c[1] -= t;
            c[2] += t;
            c[2] -= 1;
            c[p+1] +=1;
        }
        
        c[p+1] += 1;
        c[p+x+1] -= 1;
    }
    
    for(int i = 1;i <= n;++i) b[i] = b[i-1]+c[i];
    
    for(int i = 1;i <= n;++i){
         a[i] = a[i-1]+b[i];

    }

    vector<int> p;
    for(int i = 1;i <= n;++i){
        if(a[i]<=0){
            p.push_back(i);
        } 
    }
    cout<<p.size()<<endl;
    for(auto it:p) cout<<it<<" ";
    cout<<endl;
    
    
    return 0;
}

不过在处理的时候要注意边界,有些伤害不一定完全打完了,可能5的伤害扩散到边界的时候还剩下2
这个时候就需要特殊处理一下了

posted @ 2022-10-20 20:43  empty_y  阅读(89)  评论(0)    收藏  举报