题目链接:点击查看

题目大意:给出一个长度为 n 的数组 a 和计算贡献的数组 sum,需要执行 m 次操作,每次操作分为下列两种类型:

  1. 1 l r x:将区间 [ l , r ] 内的 a 用 x 覆盖,即 i ∈[ l , r] , a[ i ] = x,且 sum[ i ] += abs( a[ i ] - x )
  2. 2 l r:询问区间 [ l , r ] 内的 sum 数组之和

题目分析:修改时直接将元素相同的区间统一处理即可,这里作为一个剪枝,可以让时间复杂度均摊下来是 nlogn 的,写好pushdown和pushup两个函数的细节,剩下的码就好了,需要注意的是,cover 只用上传就好,没必要下传(因为下传 cover 没有意义)

稍微证明一下复杂度,假设对于某段区间内的元素相同的话我们将其“合并”为一个整体,那么对于每次修改来说,至多增加两个整体,也就是说最坏的情况就是将一个整体从中间修改,然后分割成了三个整体

如此一来我们按照最坏的时间复杂度去计算修改的代价,也就是:

  1. 第一次将 n 个整体合并成一个整体:O( nlogn )
  2. 后面的 n/2 次将一个整体每次增加两个整体,每次修改的复杂度是 O( logn ),此时数组又变为了 n 个整体
  3. 接下来再一次将 n 个整体合并成一个整体:O( nlogn )
  4. 后面的 n/2 次再继续每次增加两个整体,每次复杂度是 O( logn )

如此一来不难看出,“合并” 操作累加起来的复杂度不会超过 2*nlogn 次,所以均摊下来的时间复杂度仍然是 O( nlogn ) 的,只不过多了点常数罢了

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;struct Node
{int l,r;LL val,sum,len,lazy;bool cover;
}tree[N<<2];void pushup(int k)
{tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;if(tree[k<<1].cover&&tree[k<<1|1].cover&&tree[k<<1].val==tree[k<<1|1].val){tree[k].cover=true;tree[k].val=tree[k<<1].val;}elsetree[k].cover=false;
}void update(int k,LL val,LL add)
{tree[k].sum+=tree[k].len*add;tree[k].lazy+=add;tree[k].val=val;
}void pushdown(int k)
{if(tree[k].lazy){LL lz=tree[k].lazy;tree[k].lazy=0;update(k<<1,tree[k].val,lz);update(k<<1|1,tree[k].val,lz);}
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].len=r-l+1;tree[k].sum=tree[k].val=tree[k].lazy=0;if(l==r){tree[k].cover=true;tree[k].val=l;return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}void update(int k,int l,int r,LL val)
{if(tree[k].l>r||tree[k].r<l)return;if(tree[k].l>=l&&tree[k].r<=r&&tree[k].cover){update(k,val,llabs(tree[k].val-val));return;}pushdown(k);update(k<<1,l,r,val);update(k<<1|1,l,r,val);pushup(k);
}LL query(int k,int l,int r)
{if(tree[k].l>r||tree[k].r<l)return 0;if(tree[k].l>=l&&tree[k].r<=r)return tree[k].sum;pushdown(k);return query(k<<1,l,r)+query(k<<1|1,l,r);
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);build(1,1,n);while(m--){int op;scanf("%d",&op);if(op==1){int l,r,x;scanf("%d%d%d",&l,&r,&x);update(1,l,r,x);}else{int l,r;scanf("%d%d",&l,&r);printf("%lld\n",query(1,l,r));}}return 0;
}

CodeForces - 444C DZY Loves Colors(线段树+剪枝)相关推荐

  1. Codeforces 444C DZY Loves Colors 线段树区间更新

    // Codeforces 444C DZY Loves Colors 线段树区间更新// 题目链接:// http://codeforces.com/problemset/problem/444/C ...

  2. Codeforces 444C DZY Loves colors(分块)

    我们维护一个标记表示区间内的数是否全相同即可. 如果全相同很容易算出 a , b a,b a,b 数组需要更新多少,打标记即可. 否则暴力修改. #include <map> #inclu ...

  3. CodeForces 444C. DZY Loves Physics(枚举+水题)

    转载请注明出处:http://blog.csdn.net/u012860063/article/details/37509207 题目链接:http://codeforces.com/contest/ ...

  4. CodeForces 444 C DZY Loves Colors

    DZY Loves Colors 题意:有n个蛋糕,起初第i个蛋糕他的颜色值为i, 现在有2个操作, 1 x  y  c 在[x, y]的蛋糕上都加上一层颜色值为c的蛋糕片,加了这个蛋糕片之后,会产生 ...

  5. Codeforces 444 C - DZY Loves Colors

    C - DZY Loves Colors 思路: 分块,复杂度有点玄学,和普通分块不同的是在这个块被一次染色的时候暴力染整个块. 代码: #pragma GCC optimize(2) #pragma ...

  6. [Codeforces Round #254 div1] C.DZY Loves Colors 【线段树】

    题目链接:CF Round #254 div1 C 题目分析 这道题目是要实现区间赋值的操作,同时还要根据区间中原先的值修改区间上的属性权值. 如果直接使用普通的线段树区间赋值的方法,当一个节点表示的 ...

  7. Codeforces 446C —— DZY Loves Fibonacci Numbers(线段树)

    题目:DZY Loves Fibonacci Numbers 题意比較简单,不解释了. 尽管官方的题解也是用线段树,但还利用了二次剩余. 可是我没有想到二次剩余,然后写了个感觉非常复杂度的线段树,还是 ...

  8. Codeforces 446C. DZY Loves Fibonacci Numbers【斐波那契+线段树】

    C. DZY Loves Fibonacci Numbers [题目描述] 传送门 [题解] 我们可以知道斐波那契数列有两个性质: ∑i=1nFi=Fn+2−F2\sum_{i=1}^{n} F_i= ...

  9. Codeforces 446C. DZY Loves Fibonacci Numbers (Fibonacci + 线段树)

    Description In mathematical terms, the sequence F n of Fibonacci numbers is defined by the recurrenc ...

最新文章

  1. String与StringBuffer 理解
  2. 上行数据和下行数据什么意思_上行带宽和下行带宽什么意思?
  3. 2020-05-02 自动控制原理常用术语
  4. [ZT ref=null]Javascript的IE和Firefox兼容性汇编
  5. 项目打包部署到Tomcat
  6. 数学难题html5小游戏答案,小学数学难题讲解及答案
  7. 解决maven打jar包报错:Could not resolve substitution to a value: ${akka.stream.materializer}
  8. 怎么把4张图片合成一张_暴露年龄的20张图片,最后一张是什么?求解
  9. c语言基于easyX樱花特效,C++基于easyx图形库实现推箱子游戏
  10. NLPIR使用(1)
  11. [Swift]LeetCode593. 有效的正方形 | Valid Square
  12. 三个数比大小c语言_C语言必学知识点【结构体】用法很多,坑也很多!
  13. python3安装详细教程
  14. 语音文件怎么转换文字?这两个方法就能轻松解决。
  15. jQuery mobile ——制作表单
  16. oracle的dual用法
  17. php unpack 原理,unpack
  18. 安装了winRAR 但压缩文件没有显示winRAR图标
  19. js-web前端-多语言切换-data-localize
  20. 2021-2027全球及中国红外探测器芯片行业研究及十四五规划分析报告

热门文章

  1. java加法器_javacc例子:加法器
  2. 数据丢失与重复_大数据面试题分享-恭喜这位朋友刚毕业拿到了20K
  3. StrickyAssignor 分配策略
  4. 动态数据源切换的底层原理-DynamicDataSource
  5. Spring 中常用的设计模式对比
  6. 什么是Starter
  7. spring cloud netflix
  8. 百万数据报表导出:需求以及思路分析
  9. 使用传统的方式,遍历集合,对集合中的数据进行过滤
  10. Zuul简介及代码示例