首页 > 其他分享 >二重差分

二重差分

时间:2022-10-20 20:55:42浏览次数:76  
标签:10 题目 int 二重 差分 支撑点 伤害

题目链接


题目大意:

小明在游戏中搭建了一堵长为的城墙,墙上有个支撑点。为了知道墙是否足够坚固,小明喊来他的好朋友小刚帮助他进行测试。
小刚有一种特殊的炮弹可以对墙上任意一个支撑点进行轰击,收到轰击的支撑点将受到点伤害,此外,炮弹还会对个支撑点造成溅射伤害(受到的伤害依次减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
这个时候就需要特殊处理一下了

标签:10,题目,int,二重,差分,支撑点,伤害
From: https://www.cnblogs.com/empty-y/p/16811183.html

相关文章

  • POJ 1201 Intervals 差分约束
    ​​http://poj.org/problem?id=1201​​TLE了很久,因为用了cin.....思路和其他差分约束差不多,​​http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html​​......
  • Gym - 101147J Whistle's New Car 树上差分
    J.Whistle'sNewCartimelimitpertestmemorylimitpertestinputoutputWhistlehasboughtanewcar,whichhasaninfinitefueltankcapacity.Hediscoveredani......
  • 运用离散化缩小不必要的范围+差分:只通过对两个区间的端点进行加减操作即可使这段区间
    原题链接:https://codeforces.com/gym/403650/problem/C   题目的原意是:给定n个区间,求1-1e9这个数轴上,对于每一个数点,在给定区间上出现过的最大值一个最朴素的想法......
  • 【复习(雾)笔记】差分/树上差分
    差分/树上差分(雾)前言说实话,写这东西挺迷的,按道理说这玩意我应该会,但是做题的时候又不会,跟新学一样,就离谱。差分这东西就挺神奇的,前后加一减一就能维护区间。开始觉得......
  • 算法基础(五)| 差分算法及模板详解
    ⭐写在前面的话:本系列文章旨在复习算法刷题中常用的基础算法与数据结构,配以详细的图例解释,总结相应的代码模板,同时结合例题以达到最佳的学习效果。本专栏面向算法零基础但有......
  • 前缀和、差分
    前缀和类似于数列,s[i]=s[i-1]+a[i],  s[r]-s[l-1]等于l到r的所有项之和  求前缀和运算:constintN=1e5+10;intsum[N],a[N];//sum[i]=a[1]+a[2]+a[3]......
  • 洛谷 P3530 / bzoj2788【tarjan】【差分约束】
    判断是否有解可以使用差分约束。求解赛车手的成绩的取值可以使用Floyd。但是\(O(n^3)\)会TLE。可以先进行一次缩点。然后进行Floyd求出每一个连通块内的最长路径......
  • 差分约束模板补坑与学习
    很久以前就学了差分约束,但是一直没搞懂,也懒得搞懂。今天看板子,脑补了几秒钟突然就懂了。对于一个不等式,\(x_i-x_j\lek\),可以变形:\(x_i\lex_j+k\)。这跟最短......
  • 差分约束
    1、问题类型描述差分约束是一种特殊的\(n\)元一次不等式组,它包含\(n\)个变量\(x_1,x_2,\cdotsx_n\)以及\(m\)个约束条件。每个约束条件是由两个其中的变量做......
  • P2680 [NOIP2015 提高组] 运输计划 (树上差分-边差分)
    P2680题目的大意就是走完m条路径所需要的最短时间(边权是时间),其中我们可以把一条边的权值变成0(也就是题目所说的虫洞)。可以考虑二分答案x,找到一条边,使得所有大于x的路径......