分块+lazy 或者 线段树+lazy Codeforces Round #254 (Div. 2) E
2 seconds
256 megabytes
standard input
standard output
DZY loves colors, and he enjoys painting.
On a colorful day, DZY gets a colorful ribbon, which consists of n units (they are numbered from 1 to n from left to right). The color of the i-th unit of the ribbon is i at first. It is colorful enough, but we still consider that the colorfulness of each unit is 0 at first.
DZY loves painting, we know. He takes up a paintbrush with color x and uses it to draw a line on the ribbon. In such a case some contiguous units are painted. Imagine that the color of unit i currently is y. When it is painted by this paintbrush, the color of the unit becomes x, and the colorfulness of the unit increases by |x - y|.
DZY wants to perform m operations, each operation can be one of the following:
- Paint all the units with numbers between l and r (both inclusive) with color x.
- Ask the sum of colorfulness of the units between l and r (both inclusive).
Can you help DZY?
The first line contains two space-separated integers n, m (1 ≤ n, m ≤ 105).
Each of the next m lines begins with a integer type (1 ≤ type ≤ 2), which represents the type of this operation.
If type = 1, there will be 3 more integers l, r, x (1 ≤ l ≤ r ≤ n; 1 ≤ x ≤ 108) in this line, describing an operation 1.
If type = 2, there will be 2 more integers l, r (1 ≤ l ≤ r ≤ n) in this line, describing an operation 2.
For each operation 2, print a line containing the answer — sum of colorfulness.
3 3
1 1 2 4
1 2 3 5
2 1 3
8
3 4
1 1 3 4
2 1 1
2 2 2
2 3 3
3
2
1
10 6
1 1 5 3
1 2 7 9
1 10 10 11
1 3 8 12
1 1 10 3
2 1 10
129
In the first sample, the color of each unit is initially [1, 2, 3], and the colorfulness is [0, 0, 0].
After the first operation, colors become [4, 4, 3], colorfulness become [3, 2, 0].
After the second operation, colors become [4, 5, 5], colorfulness become [3, 3, 2].
So the answer to the only operation of type 2 is 8.
题意
一开始,a[i]=i,b[i]=0,然后有两个操作:
1.使得[l,r]的b[i]+=fabs(x-a[i]),a[i]=x
2.查询[l,r]的b[i]和
思路一:线段树+lazy
这个应该比较轻松吧,线段树的lazy大家应该都会,这里我就不多说了。
思路二:分块+lazy
终于感觉到卿学姐之前的分块写法的漏洞了——代码量大,虽然思路清晰,但是很容易错TAT,我debug了1个小时多。
这里的关键就是如何学习lazy技巧了。
刚开始的时候我的lazy就直接保存之前输入的val,就和线段树一样那个样子更新,但是最后我写着写着发现,代码量好像有点大啊,就果断看了一下卿学姐的代码,瞬间感觉自己好傻。
这里,我们用lastval表示之前该块里面的所有的a[i]更新以后的权值,然后lazy就表示如果是重复更新的话,那么lazy[i] += abs(val - lastval[i])即可,然后这里我们再用一个sum保存整个块的val。
当询问左右区间的时候,就直接暴力即可:ans += lazy[j] + b[j],当询问中间区间(即块)的时候,就是ans+=sum[j]
我的代码:按照卿学姐以前的习惯写的
//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 1e5 + ;
LL a[maxn], b[maxn], add[maxn], sum[maxn], lazy[maxn], lastval[maxn];
int block, num, belong[maxn], l[maxn], r[maxn];
int n, m; void build(){
block = sqrt(n); num = n / block;
if (n % block) num++;
for (int i = ; i <= num; i++)
l[i] = (i - ) * block + , r[i] = i * block;
for (int i = ; i <= n; i++)
belong[i] = (i - ) / block + ;
} ///如果lazy保存的是目前要更新的值x,那么代码的复杂度就会大大增加
///如果lazy保存的是x减pre_lazy_val,那么代码的复杂度就会大大减少,但是会多一个空间
///叫做lastval,表示保存之前的val
void update(int x, int y, int val){
if(belong[x] == belong[y]){
if (lastval[belong[x]]){
for (int i = l[belong[x]]; i <= r[belong[x]]; i++) a[i] = lastval[belong[x]];
lastval[belong[x]] = ;
}
for (int i = x; i <= y; i++){
b[i] += abs(val - a[i]); sum[belong[x]] += abs(val - a[i]);
a[i] = val;
}
return ;
}
///对x的修改
if (lastval[belong[x]]){
for (int i = l[belong[x]]; i <= r[belong[x]]; i++) a[i] = lastval[belong[x]];
lastval[belong[x]] = ;
}
for (int i = x; i <= r[belong[x]]; i++){
b[i] += abs(val - a[i]); sum[belong[x]] += abs(val - a[i]);
a[i] = val;
}
///对y的修改
if (lastval[belong[y]]){
for (int i = l[belong[y]]; i <= r[belong[y]]; i++) a[i] = lastval[belong[y]];
lastval[belong[y]] = ;
}
for (int i = l[belong[y]]; i <= y; i++){
b[i] += abs(val - a[i]); sum[belong[y]] += abs(val - a[i]);
a[i] = val;
} ///对块的修改
for (int i = belong[x] + ; i < belong[y]; i++){
if (lastval[i]){
lazy[i] += abs(val - lastval[i]);
sum[i] += 1LL * (r[i] - l[i] + ) * abs(val - lastval[i]);
lastval[i] = val;
}
else {
for (int j = l[i]; j <= r[i]; j++){
b[j] += abs(val - a[j]);
sum[i] += abs(val - a[j]);
a[j] = val;//////////////这里增加了
}
lastval[i] = val;
}
}
} LL query(int x, int y){
LL ans = ;
if (belong[x] == belong[y]){
for (int i = x; i <= y; i++) ans += b[i] + lazy[belong[x]];
return ans;
}
///对x进行操作
for (int i = x; i <= r[belong[x]]; i++)
ans += b[i] + lazy[belong[x]]; ///对y进行操作
for (int i = l[belong[y]]; i <= y; i++)
ans += b[i] + lazy[belong[y]]; ///对块进行操作
for (int i = belong[x] + ; i < belong[y]; i++)
ans += sum[i];
return ans;
} int main(){
cin >> n >> m;
for (int i = ; i <= n; i++) a[i] = i;
build();
for (int i = ; i <= m; i++){
int ty, x, y, z;
scanf("%d", &ty);
if (ty == ){
scanf("%d%d%d", &x, &y, &z);
update(x, y, z);
}
if (ty == ){
scanf("%d%d", &x, &y);
printf("%lld\n", query(x, y));
}
}
return ;
}
/*
10 10
1 1 5 3
2 1 10
1 2 7 9
2 1 10
1 10 10 11
2 1 10
1 3 8 12
2 1 10
1 1 10 3
2 1 10
*/
写完了以后我就发现自己太年轻了,果然分块还能写的更加简便啊= =。 来自:链接
#include <bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&(-x))
const int maxn = 1e5 + ; inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} int n , m , unit , a[maxn] ;
long long extra[maxn] , lz[maxn] , ls[maxn] , b[maxn]; int main(){
n = read() , m = read();
unit = sqrt( n );
for(int i = ; i < n ; ++ i) a[i] = i + ;
while( m -- ){
int op = read() , l = read() , r = read() , x;
--l;
--r;
if( op == ){
x = read();
for(int i = l ; i <= r ; ){
int idx = i / unit;
int st = idx * unit;//表示目前块的左端点,但是要注意,这里没有+1
int ed = min( n , (idx + ) * unit );//表示目前块的右端点
if(i == st && r >= ed - ){
if( ls[idx] ){
extra[idx] += 1LL * abs(x - ls[idx]) * (ed - st) ;
lz[idx] += abs(x - ls[idx]);
ls[idx] = x;
}
else{
for(int j = st; j < ed; ++j){
b[j] += abs(a[j] - x );
extra[idx] += abs(a[j] - x);
a[j] = x;
}
ls[idx] = x;
}
i = ed;
}
else{///对于块的两端东西进行暴力
if(ls[idx]){
for(int j = st; j < ed; ++j) a[j] = ls[idx];
ls[idx] = ;
}
extra[idx] += abs(a[i] - x);
b[i] += abs(a[i] - x);
a[i] = x;
++i;
}
}
}else{
long long res = ;
for(int i = l; i <= r ;){//对于中间,全都保存在extra当中?
int idx = i / unit;
int st = idx * unit;
int ed = min(n, (idx + ) * unit);
if(i == st && r >= ed - ){
res += extra[idx];
i = ed;
}else{///对于两端进行暴力
res += b[i] + lz[idx];
++i;
}
}
printf("%lld\n" , res);
}
}
return ;
}
分块+lazy 或者 线段树+lazy Codeforces Round #254 (Div. 2) E的更多相关文章
- 【动态规划】【线段树】 Codeforces Round #426 (Div. 1) B. The Bakery
给你一个序列,让你划分成K段,每段的价值是其内部权值的种类数,让你最大化所有段的价值之和. 裸dp f(i,j)=max{f(k,j-1)+w(k+1,i)}(0<=k<i) 先枚举j,然 ...
- 【线段树】Codeforces Round #393 (Div. 1) C. Nikita and stack
就是给你一些元素的进栈 出栈操作,不按给定的顺序,要求你对于每次输入,都依据其及其之前的输入,判断出栈顶的元素是谁. 用线段树维护,每次push,将其位置的值+1,pop,将其位置的值-1.相当于寻找 ...
- Codeforces Round 254 (Div. 2)
layout: post title: Codeforces Round 254 (Div. 2) author: "luowentaoaa" catalog: true tags ...
- Codeforces Round #254 (Div. 1) C DZY Loves Colors
http://codeforces.com/contest/444/problem/C 题意:给出一个数组,初始时每个值从1--n分别是1--n. 然后两种操作. 1:操作 a.b内的数字是a,b内 ...
- Codeforces Round #254 (Div. 1) C. DZY Loves Colors 线段树
题目链接: http://codeforces.com/problemset/problem/444/C J. DZY Loves Colors time limit per test:2 secon ...
- Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))
题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...
- Codeforces Round #254 (Div. 1) C. DZY Loves Colors 分块
C. DZY Loves Colors 题目连接: http://codeforces.com/contest/444/problem/C Description DZY loves colors, ...
- Codeforces Round #254 (Div. 2) B. DZY Loves Chemistry (并查集)
题目链接 昨天晚上没有做出来,刚看题目的时候还把题意理解错了,当时想着以什么样的顺序倒,想着就饶进去了, 也被题目下面的示例分析给误导了. 题意: 有1-n种化学药剂 总共有m对试剂能反应,按不同的 ...
- Codeforces Round #254 (Div. 1) D - DZY Loves Strings
D - DZY Loves Strings 思路:感觉这种把询问按大小分成两类解决的问题都很不好想.. https://codeforces.com/blog/entry/12959 题解说得很清楚啦 ...
随机推荐
- 王者荣耀交流协会final冲刺第五次scrum会议
成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐,王磊拍照. master:高远博 2.时间跨度 2017年12月5日 18:00 - 18:31,总计31分钟 3.地点 一食堂二楼沙发座椅 ...
- 机器学习笔记(4)Logistic回归
模型介绍 对于分类问题,其得到的结果值是离散的,所以通常情况下,不适合使用线性回归方法进行模拟. 所以提出Logistic回归模型. 其假设函数如下: \[ h_θ(x)=g(θ^Tx) \] 函数g ...
- FormsAuthentication.SetAuthCookie 方法登录
FormsAuthentication.SetAuthCookie 方法,登录的原理. FormsAuthentication.SetAuthCookie 方法登录的过期时间. 登录相关阅读 asp. ...
- LoadRunner脚本增强技巧之参数化(一)
参数化的方式有两种,一种通过File引入参数值,一种通过数据库引入参数值.本篇介绍File方式引入参数值. 一.File方式参数化过程 1.在脚本中找到需要做参数化的字符串,选中,右键点击,选择Rep ...
- presence_of_element_located与visibility_of_element_located区别
selenium 问题:加了显性等待后,操作元素依然出错 背景: 用WebDriverWait时,一开始用的是presence_of_element_located,我对它的想法就是他就是用来等待 ...
- 【HLSDK系列】Delta 详解
服务端和客户端总是需要互相交换数据,来做到实时的游戏体验. 很久之前,我们的网速都不是很快,甚至带宽只有 1Mbps (128KB/s)这样的速度,作为当时一个网络实时对战游戏,每时每刻都要传递数据, ...
- BZOJ1069 [SCOI2007]最大土地面积 【凸包 + 旋转卡壳】
题目链接 BZOJ1069 题解 首先四个点一定在凸包上 我们枚举对角线,剩下两个点分别是两侧最远的点 可以三分,复杂度\(O(n^2logn)\) 可以借鉴旋转卡壳的思想,那两个点随着对角线的一定单 ...
- CVE-2017-16995 Ubuntu16.04本地提权漏洞复现
0x01 前言 该漏洞由Google project zero发现.据悉,该漏洞存在于带有 eBPF bpf(2)系统(CONFIG_BPF_SYSCALL)编译支持的Linux内核中,是一个内存任意 ...
- JAVA本地TXT文件解决中文乱码问题
import java.io.*; public class ReadFile { public static void main(String[] args) { try { File file = ...
- bzoj2296: 【POJ Challenge】随机种子(思维题/水题)
有点类似CF某场div2T1... 前面接上1234567890000000,后面加上x+(1234567890000000%x)就可以保证是x的倍数了 #include<iostream> ...