Problem J: Alex’s Foolish Function

Time Limit: 8 Sec  Memory Limit: 128 MB
Submit: 18  Solved: 2

Description

Alex has an array F which size is n, initially each element’s value is zero. Now he wants to operate the array, he has 4 different functions:
1) Function A(l, r):
Add the elements between l to r (inclusive) where the ith add i - l + 1, for instance, if l is 4,
r is 6 and the elements between 4 to 6 is 3 4 10, after this operation, these elements will become 4 6 13.
2) Function B(l, r):
Add the elements between l to r (inclusive) where the ith add r - i + 1, for instance, if l is 4,
r is 6 and the elements between 4 to 6 is 3 4 10, after this operation, these elements will become 6 6 11.
3) Function C(l, r, x):
Set all the elements(between l to r) to x, for instance, if l is 4, r is 6 and the elements
between 4 to 6 is 3 4 10, and x = 2, after this operation, these elements will become 2 2 2.
4) Function S(l, r):
Output Fl + Fl+1 + Fl+2 + ...+ Fr. 

Input

Input start with an integer T(1 <= T <= 5), denoting the number of test case.
For each test case, first line contains n, m (1 <= n <= 200000, 1 <= m <= 100000), denoting the array’size and the number of operations.
Next m lines, each line contains an operation, formatting as
A l r
B l r
C l r x
S l r 

Output

For each S Function operations, output the sum. 

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(分块+延迟标记)的更多相关文章

  1. QAU 17校赛 J题 剪丝带(完全背包变形)

    题意: 剪一段丝带,对于剪完后的每一段丝带长度必须是a,b,c 输入丝带的长度  n 和  a  b  c 输出一个整数,代表最多能剪成多少段 样例输入 5 5 3 2 7 5 5 2 样例输出 2 ...

  2. QAU 18校赛 J题 天平(01背包 判断能否装满)

    问题 J: 天平 时间限制: 1 Sec  内存限制: 128 MB提交: 36  解决: 9[提交][状态][讨论版][命题人:admin] 题目描述 天平的右端放着一件重量为w的物品.现在有n个重 ...

  3. 上海高校金马五校赛 J - 小Y写文章

    题目大意: 给你n个数字, 定义不连贯值为, max(abs(a[ i ] - b[ i ])) ,现在让你把m个新的数字插入n + 1 个空位中,使得不连贯值最小. 思路:二分不连贯值, 每次进行二 ...

  4. 福建工程学院第十四届ACM校赛J题题解

    第六集,想不到你这个浓眉大眼的都叛变革命了 题意: 给你两个只包含01的字符串S和T,问你在允许一次错误的情况下,T是否能成为S的子串 思路: 这个问题的解法挺多,我是用fft匹配的,也比较简单,针对 ...

  5. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  6. 2014上半年acm总结(1)(入门+校赛)

    大一下学期才开始了acm,不得不说有一点迟,但是acm确实使我的生活充实了很多,,不至于像以前一样经常没事干=  = 上学期的颓废使我的c语言学的渣的一笔..靠考前突击才基本掌握了语法 寒假突然醒悟, ...

  7. HZNU第十二届校赛赛后补题

    愉快的校赛翻皮水! 题解 A 温暖的签到,注意用gets #include <map> #include <set> #include <ctime> #inclu ...

  8. 牛客网多校赛第9场 E-Music Game【概率期望】【逆元】

    链接:https://www.nowcoder.com/acm/contest/147/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...

  9. 2014哈商大ICPC/ACM校赛解题报告

    被debug邀请去參加校赛,哎,被虐..我对不起工大.. 由于本人不搞ACM,算法处于HelloWorld水准.. 虽然题目除了鸟不拉屎星人之外都非常水,但我能做到这个程度,全然是超水平发挥了.. 数 ...

随机推荐

  1. $.ajax()与$.post()区别

    当使用$.ajax时: var name = $('#txtUserName').val(); var pwd = $('#txtPassWord').val(); var param = " ...

  2. Maven - 配置镜像仓库

    默认仓库的配置(全球中央仓库): 可以打开maven的安装目录/conf/settings.xml文件,配置镜像,找到如下一段配置,这里默认没有配置任何镜像,但是有一个被注释的配置范例: id: 镜像 ...

  3. MySQL超大表如何提高count速度

    经常用到count统计记录数,表又超级大,这时候sql执行很慢,就是走索引,也是很慢的,怎么办呢? 1.这个时候我们就要想为什么这么慢:根本原因是访问的数据量太大,就算只计算记录数也是很慢的. 2.如 ...

  4. DNS介绍与安装使用

    DNS简介 DNS是互联网的一项服务.它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.DNS使用TCP和UDP的53号端口. DNS服务的基本概念 在使用DNS前需要了解 ...

  5. python简介,数据类型,input,if语句

      1. python的起源 python的创始人为吉多·范罗苏姆(龟叔Guido van Rossum),1989年的圣诞节期间,龟叔为了在阿姆斯特丹打发时间 决心开发一个新的脚本程序解释器,作为A ...

  6. python入门基本知识

    1. 什么是语言 语言是一个事物与另外一个事物沟通的介质. python则是人(程序员)与计算机沟通的介质. 2. 什么是编程 编程就是程序员将自己想要让计算机做的事情用编程语言翻译出来写到一系列的文 ...

  7. you do not permission to access / no this server

    最近在学习Linux下的httpd服务,自己写了一个虚拟主机的配置文件 重启之后,怎么访问都是出现以下的内容, do not permission to access / no this server ...

  8. select into from 和 insert into select

    select into from 和 insert into select都是用来复制表, 两者的主要区别为: select into from 要求目标表不存在,因为在插入时会自动创建. inser ...

  9. ASCII码排序 南阳acm4

    ASCII码排序 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符.   输入 第一行输 ...

  10. POJ 3484 二分

    Showstopper Description Data-mining huge data sets can be a painful and long lasting process if we a ...