NBUT校赛 J Alex’s Foolish Function(分块+延迟标记)
Problem J: Alex’s Foolish Function
Time Limit: 8 Sec Memory Limit: 128 MB
Submit: 18 Solved: 2
Description
Add the elements between l to r (inclusive) where the ith add i - l + 1, for instance, if l is 4,
Add the elements between l to r (inclusive) where the ith add r - i + 1, for instance, if l is 4,
Set all the elements(between l to r) to x, for instance, if l is 4, r is 6 and the elements
Output Fl + Fl+1 + Fl+2 + ...+ Fr.
Input
B l r
C l r x
Output
Sample Input
1
5 4
A 1 3
B 2 5
C 1 1 2
S 1 5
Sample Output
17
正规做法是线段树维护区间的左加、右加或者覆盖信息,然而想用分块写一写。
对于A操作,每一个块维护起始的加数,以及A操作的次数,
对于B操作,每一个块维护末尾的加数,以及B操作的次数,
对于C操作,每一个块维护准备覆盖的值val。
显然对于A操作和B操作维护的信息,是满足区间加法的,即[1,4]A操作一次,[2,4]A操作一次,比如当前块是[2,4],记为Bx,那么我们可以记录起始的加数:(2-1+1)+(2-2+1)=3,A操作次数为2,即arr[2]+=3,arr[3]+=(3+2),arr[4]+=(3+2+2),然后我们可以发现这是一个等差数列,可以用公式快速得到有延迟标记A操作的区间和,即$(Bx.lazy_A+(Bx.lazy_A+Bx.len-1))*Bx.len/2+Bx.sum$,然后B操作也同理,最后加上本身的$Bx.sum$即可(这里要注意AB操作不能重复加Bx.sum);B操作同理;C操作的话由于是覆盖那么在更新的时候把更新到的块的$lazy_c$更新,并把$lazy_A$与$lazy_B$取消掉即可,由于可能$lazy_c$为0,初始值应设为一个不太可能用到的数,比如$-INF$。
代码:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 200010;
const int M = 450;
struct Block
{
int l, r;
LL lazy1, lazy2, lazy3, sum;
LL c1, c2; inline int len()
{
return r - l + 1;
}
};
Block B[M];
LL arr[N];
int belong[N], unit, bcnt;
int n, m; void init()
{
int i;
unit = sqrt(n);
bcnt = n / unit;
if (n % unit)
++bcnt;
for (i = 1; i <= bcnt; ++i)
{
B[i].l = (i - 1) * unit + 1;
B[i].r = i * unit;
B[i].sum = 0LL;
B[i].lazy1 = 0LL;
B[i].lazy2 = 0LL;
B[i].lazy3 = -INF;
B[i].c1 = B[i].c2 = 0LL;
}
B[bcnt].r = n;
for (i = 1; i <= n; ++i)
{
arr[i] = 0LL;
belong[i] = (i - 1) / unit + 1;
}
}
void pushdown(int bx)
{
if (B[bx].lazy3 != -INF)
{
for (int i = B[bx].l; i <= B[bx].r; ++i)
arr[i] = B[bx].lazy3;
B[bx].lazy3 = -INF;
}
if (B[bx].lazy1)
{
for (int i = B[bx].l; i <= B[bx].r; ++i)
{
arr[i] += + B[bx].lazy1;
B[bx].lazy1 += B[bx].c1;
}
B[bx].lazy1 = 0LL;
B[bx].c1 = 0LL;
}
if (B[bx].lazy2)
{
for (int i = B[bx].r; i >= B[bx].l; --i)
{
arr[i] += + B[bx].lazy2;
B[bx].lazy2 += B[bx].c2;
}
B[bx].lazy2 = 0LL;
B[bx].c2 = 0LL;
}
B[bx].sum = 0LL;
for (int i = B[bx].l; i <= B[bx].r; ++i)
B[bx].sum += arr[i];
}
void update(int l, int r, int ops, LL val = 0LL)
{
int bl = belong[l], br = belong[r];
int i;
if (bl == br)
{
pushdown(bl);
if (ops == 1)
{
for (i = l; i <= r; ++i)
{
B[bl].sum -= arr[i];
arr[i] = arr[i] + (LL)(i - l + 1LL);
B[bl].sum += arr[i];
}
}
else if (ops == 2)
{
for (i = r; i >= l; --i)
{
B[bl].sum -= arr[i];
arr[i] = arr[i] + (LL)(r - i + 1LL);
B[bl].sum += arr[i];
}
}
else if (ops == 3)
{
for (i = l; i <= r; ++i)
{
B[bl].sum -= arr[i];
arr[i] = val;
B[bl].sum += arr[i];
}
}
}
else
{
//left
pushdown(bl);
if (ops == 1)
{
for (i = l; i <= B[bl].r; ++i)
{
B[bl].sum -= arr[i];
arr[i] = arr[i] + (LL)(i - l + 1LL);
B[bl].sum += arr[i];
}
}
else if (ops == 2)
{
for (i = B[bl].r; i >= l; --i)
{
B[bl].sum -= arr[i];
arr[i] = arr[i] + (LL)(r - i + 1LL);
B[bl].sum += arr[i];
}
}
else if (ops == 3)
{
for (i = l; i <= B[bl].r; ++i)
{
B[bl].sum -= arr[i];
arr[i] = val;
B[bl].sum += arr[i];
}
}
//right
pushdown(br);
if (ops == 1)
{
for (i = B[br].l; i <= r; ++i)
{
B[br].sum -= arr[i];
arr[i] = arr[i] + (LL)(i - l + 1LL);
B[br].sum += arr[i];
}
}
else if (ops == 2)
{
for (i = r; i >= B[br].l; --i)
{
B[br].sum -= arr[i];
arr[i] = arr[i] + (LL)(r - i + 1LL);
B[br].sum += arr[i];
}
}
else if (ops == 3)
{
for (i = B[br].l; i <= r; ++i)
{
B[br].sum -= arr[i];
arr[i] = val;
B[br].sum += arr[i];
}
}
for (i = bl + 1; i < br; ++i)
{
if (ops == 3)
{
B[i].lazy3 = val;
B[i].c1 = 0LL;
B[i].c2 = 0LL;
B[i].lazy1 = 0LL;
B[i].lazy2 = 0LL;
}
else if (ops == 2)
{
B[i].lazy2 += (LL)(r - B[i].r + 1LL);
++B[i].c2;
}
else if (ops == 1)
{
B[i].lazy1 += (LL)(B[i].l - l + 1LL);
++B[i].c1;
}
}
}
}
LL query(int l, int r)
{
int bl = belong[l], br = belong[r], i;
LL sum = 0LL;
if (bl == br)
{
pushdown(bl);
for (i = l; i <= r; ++i)
sum += arr[i];
return sum;
}
else
{
pushdown(bl);
pushdown(br);
for (i = l; i <= B[bl].r; ++i)
sum += arr[i];
for (i = B[br].l; i <= r; ++i)
sum += arr[i];
for (i = bl + 1; i < br; ++i)
{
if (B[i].lazy3 != -INF)
sum += (LL)B[i].len() * B[i].lazy3;
if (B[i].lazy1)
sum += (B[i].lazy1 + B[i].lazy1 + (LL)(B[i].len() - 1LL) * B[i].c1) * (LL)B[i].len() / 2LL;
if (B[i].lazy2)
sum += (B[i].lazy2 + B[i].lazy2 + (LL)(B[i].len() - 1LL) * B[i].c2) * (LL)B[i].len() / 2LL;
if (B[i].lazy3 == -INF)
sum += B[i].sum;
}
return sum;
}
}
int main(void)
{
// fin("test0.in");
// fout("data_wa.txt");
int tcase, l, r, v;
char ops[4];
scanf("%d", &tcase);
while (tcase--)
{
scanf("%d%d", &n, &m);
init();
while (m--)
{
scanf("%s", ops);
if (ops[0] == 'A')
{
scanf("%d%d", &l, &r);
update(l, r, 1);
}
else if (ops[0] == 'B')
{
scanf("%d%d", &l, &r);
update(l, r, 2);
}
else if (ops[0] == 'C')
{
scanf("%d%d%d", &l, &r, &v);
update(l, r, 3, (LL)v);
}
else
{
scanf("%d%d", &l, &r);
printf("%lld\n", query(l, r));
}
}
}
return 0;
}
NBUT校赛 J Alex’s Foolish Function(分块+延迟标记)的更多相关文章
- QAU 17校赛 J题 剪丝带(完全背包变形)
题意: 剪一段丝带,对于剪完后的每一段丝带长度必须是a,b,c 输入丝带的长度 n 和 a b c 输出一个整数,代表最多能剪成多少段 样例输入 5 5 3 2 7 5 5 2 样例输出 2 ...
- QAU 18校赛 J题 天平(01背包 判断能否装满)
问题 J: 天平 时间限制: 1 Sec 内存限制: 128 MB提交: 36 解决: 9[提交][状态][讨论版][命题人:admin] 题目描述 天平的右端放着一件重量为w的物品.现在有n个重 ...
- 上海高校金马五校赛 J - 小Y写文章
题目大意: 给你n个数字, 定义不连贯值为, max(abs(a[ i ] - b[ i ])) ,现在让你把m个新的数字插入n + 1 个空位中,使得不连贯值最小. 思路:二分不连贯值, 每次进行二 ...
- 福建工程学院第十四届ACM校赛J题题解
第六集,想不到你这个浓眉大眼的都叛变革命了 题意: 给你两个只包含01的字符串S和T,问你在允许一次错误的情况下,T是否能成为S的子串 思路: 这个问题的解法挺多,我是用fft匹配的,也比较简单,针对 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- 2014上半年acm总结(1)(入门+校赛)
大一下学期才开始了acm,不得不说有一点迟,但是acm确实使我的生活充实了很多,,不至于像以前一样经常没事干= = 上学期的颓废使我的c语言学的渣的一笔..靠考前突击才基本掌握了语法 寒假突然醒悟, ...
- HZNU第十二届校赛赛后补题
愉快的校赛翻皮水! 题解 A 温暖的签到,注意用gets #include <map> #include <set> #include <ctime> #inclu ...
- 牛客网多校赛第9场 E-Music Game【概率期望】【逆元】
链接:https://www.nowcoder.com/acm/contest/147/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
- 2014哈商大ICPC/ACM校赛解题报告
被debug邀请去參加校赛,哎,被虐..我对不起工大.. 由于本人不搞ACM,算法处于HelloWorld水准.. 虽然题目除了鸟不拉屎星人之外都非常水,但我能做到这个程度,全然是超水平发挥了.. 数 ...
随机推荐
- LinkedHashMap使用心得
基本概念:https://www.cnblogs.com/xiaoxi/p/6170590.html 遇到问题: 1.构造方法 public static LinkedHashMap<Strin ...
- java基础必备单词讲解 day two
variable 变量 count 统计 sum 总数 salary 薪水 Scanner 接收 import 导入 eclipse 日食 control 控制 shift 改变 alt 替换键 ha ...
- .NET向WebService传值为decimal、double、int、DateTime等非string类型属性时,服务器端接收不到数据的问题
最近在做CRM项目时,使用C#调用SAP PI发布的WebService服务时遇到的问题: 向WebService传值为decimal.double.int.DateTime等非string类型数据时 ...
- Centos下使用Docker部署MySql
本文讲述 CentOS 系统 Docker 中安装 MySql 的过程 步骤 1. 拉取 Docker Hub 官方提供的mysql镜像 docker pull mysql:5.7 2.运行容器 do ...
- expect配合shell 实现自动分发秘钥文件
expect使用场景 有时候需要批量地执行一些操作,或者执行自动化的操作的时候,有些指令需要交互式地进行这就会有很多麻烦,linux下有一个程序交expect,它可以模拟键盘输入文本,省去人工干预交互 ...
- 【转载】C语言itoa()函数和atoi()函数详解(整数转字符C实现)
本文转自: C语言itoa()函数和atoi()函数详解(整数转字符C实现) 介绍 C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. int/float to ...
- swoole学习(一)----linux安装swoole
1.下载swoole 登录swoole官网 https://www.swoole.com/ 点击下载,找到github或者其他链接下载下来 放到虚拟机上. 也可以使用虚拟机下载 2.登录虚拟机 推荐使 ...
- SQL tp3.2 批量更新 saveAll
/** * 批量更新数据 * @param [array] $datas [更新数据] * @param [string] $table_name [表名] */ public function sa ...
- python3 练习题100例 (十六)鸡尾酒疗法
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = 'Fan Lijun' n = input('请输入一个大于1,小于等于20的整 ...
- 清空Fragment回退栈中某个Fragment之上的所有Fragment
根据debug信息查看Fragment回退栈的情况,具体debug代码如下: int num = getActivity().getSupportFragmentManager().getBackSt ...