F. Heroes of Making Magic III

time limit per test:3 seconds

memory limit per test:256 megabytes

input:standard input

output:standard output

I’m strolling on sunshine, yeah-ah! And doesn’t it feel good! Well, it certainly feels good for our Heroes of Making Magic, who are casually walking on a one-directional road, fighting imps. Imps are weak and feeble creatures and they are not good at much. However, Heroes enjoy fighting them. For fun, if nothing else.

Our Hero, Ignatius, simply adores imps. He is observing a line of imps, represented as a zero-indexed array of integers a of length n, where ai denotes the number of imps at the i-th position. Sometimes, imps can appear out of nowhere. When heroes fight imps, they select a segment of the line, start at one end of the segment, and finish on the other end, without ever exiting the segment. They can move exactly one cell left or right from their current position and when they do so, they defeat one imp on the cell that they moved to, so, the number of imps on that cell decreases by one. This also applies when heroes appear at one end of the segment, at the beginning of their walk.

Their goal is to defeat all imps on the segment, without ever moving to an empty cell in it (without imps), since they would get bored. Since Ignatius loves imps, he doesn’t really want to fight them, so no imps are harmed during the events of this task. However, he would like you to tell him whether it would be possible for him to clear a certain segment of imps in the above mentioned way if he wanted to.

You are given q queries, which have two types:

  • a b k — denotes that k imps appear at each cell from the interval [a, b]
  • a b - asks whether Ignatius could defeat all imps on the interval [a, b] in the way described above

Input

The first line contains a single integer n (1 ≤ n ≤ 200 000), the length of the array a. The following line contains n integersa1, a2, ..., an (0 ≤ ai ≤ 5 000), the initial number of imps in each cell. The third line contains a single integer q (1 ≤ q ≤ 300 000), the number of queries. The remaining q lines contain one query each. Each query is provided by integers ab and, possibly, k(0 ≤ a ≤ b < n, 0 ≤ k ≤ 5 000).

Output

For each second type of query output 1 if it is possible to clear the segment, and 0 if it is not.

Example

input
3
2 2 2
3
2 0 2
1 1 1 1
2 0 2
output
0
1

Note

For the first query, one can easily check that it is indeed impossible to get from the first to the last cell while clearing everything. After we add 1 to the second position, we can clear the segment, for example by moving in the following way: .

Solution

题目大意:

给定区间[0,N-1],支持两种操作:

1.区间[l,r]权值+K

2.区间是否可以删光(这里移动时不允许移动到区间之外)

这里可以删光的含义是:从一个格,可以向左/右移动一格,每移动一步,必须使左/右权值-1,当一个地方权值为0时,无法向其移动,删光即能否按照这种移动方式将这个区间中的所有权值删光。

区间上的问题显然可以考虑用线段树来实现。

问题在于这种移动方式,我们不妨考虑其性质。

对于询问一个区间是否能删光,不同的移动方法都有可能能完成,但为了方便我们只考虑其中一种方法。

对于区间$[l,r]$我们从$l$开始移动,我们就先在$l$和$l+1$之间来回,直到$l$清空,我们再在$l+1$和$l+2$之间来回,直到$l+1$清空,如此直到$r-1$和$r$

那么这样能够清空所有位置的权值的条件是:

$$a_{l}>=1$$

$$a_{l+1}-a_{l}>=0$$

$$a_{l+2}-(a_{l+1}-a_{l}+1)>=0$$

$$......$$

那么我们化简一下所有的式子可以得到:

$$a_{l}>=1$$

$$a_{l+1}-a_{l}>=0$$

$$a_{l+2}-a_{l+1}+a_{l}>=1$$

$$......$$

观察一下不等式右边,发现和项数的奇偶有关。

那么我们就可以得到一个通式:

$$a_{r}-a{r-1}+a{r-2}-a_{r-3}+...a_{l}>=[(r-l+1)mod1==0] $$

然后我们很直观的想法就是用线段树去维护这个东西,并且能分奇偶维护更加方便。

问题在于如何维护这个东西,我们做差,另$d_{i}=a_{1}-a{2}+a{3}...$

我们就可以利用这个东西,计算一个区间的值。 所以我们用线段树去维护这个东西。

对于一个区间$[l,r]$这个区间的值$D[l,r]$可以通过$d$来计算

然后我们按照奇偶分别维护,就可以了。

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
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;
}
#define MAXN 300010
#define INF 0x7fffffff
int N,Q,a[MAXN],d[MAXN];
namespace SegmentTree
{
struct SegmentTreeNode{int l,r,size; LL sum,tag[],D[]; bool f;}tree[MAXN<<];
#define ls now<<1
#define rs now<<1|1
inline void Update(int now,bool o)
{
tree[now].D[]=min(tree[ls].D[],tree[rs].D[o]);
tree[now].D[]=min(tree[ls].D[],tree[rs].D[o^]);
}
inline void PushDown(int now,bool o)
{
if (tree[now].l==tree[now].r) return;
if (tree[now].tag[])
tree[ls].D[]+=tree[now].tag[],tree[ls].tag[]+=tree[now].tag[],
tree[rs].D[o]+=tree[now].tag[],tree[rs].tag[o]+=tree[now].tag[],
tree[now].tag[]=;
if (tree[now].tag[])
tree[ls].D[]+=tree[now].tag[],tree[ls].tag[]+=tree[now].tag[],
tree[rs].D[o^]+=tree[now].tag[],tree[rs].tag[o^]+=tree[now].tag[],
tree[now].tag[]=;
}
inline void BuildTree(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r; tree[now].size=r-l+;
if (l==r) {tree[now].D[]=d[l]; tree[now].D[]=INF; return;}
int mid=(l+r)>>;
BuildTree(ls,l,mid); BuildTree(rs,mid+,r);
Update(now,tree[ls].size&);
}
inline void Modify(int now,int L,int R,LL x,bool o)
{
if (L>R) return;
int l=tree[now].l,r=tree[now].r;
PushDown(now,tree[ls].size&);
if (L<=l && R>=r) {tree[now].tag[o]+=x; tree[now].D[o]+=x; return;}
int mid=(l+r)>>;
if (L<=mid) Modify(ls,L,R,x,o);
if (R>mid) Modify(rs,L,R,x,o^(tree[ls].size&));
Update(now,tree[ls].size&);
}
inline LL Query(int now,int L,int R,bool o)
{
if (L>R) return INF;
int l=tree[now].l,r=tree[now].r;
PushDown(now,tree[ls].size&);
if (L<=l && R>=r) return tree[now].D[o];
int mid=(l+r)>>; LL re=INF;
if (L<=mid) re=min(re,Query(ls,L,R,o));
if (R>mid) re=min(re,Query(rs,L,R,o^(tree[ls].size&)));
return re;
}
}
using namespace SegmentTree;
int main()
{
N=read();
for (int i=; i<=N-; i++) a[i]=read();
d[]=a[]; for (int i=; i<=N-; i++) d[i]=a[i]-a[i-],a[i]-=a[i-];
SegmentTree::BuildTree(,,N-);
Q=read();
while (Q--)
{
int opt=read(),L=read(),R=read(),K;
if (opt==)
{
K=read(); SegmentTree::Modify(,L,R,K,L&);
if ((R-L+)&) SegmentTree::Modify(,R+,N-,-K,(R+)&),SegmentTree::Modify(,R+,N-,K,(R+)&);
}
if (opt==)
{
LL x=L>? SegmentTree::Query(,L-,L-,(L-)&):,y=SegmentTree::Query(,R,R,R&);
if ((R-L+)&) y+=x; else y-=x;
if (y!=((R-L+)&) || SegmentTree::Query(,L,R,L&)+x< || SegmentTree::Query(,L,R,(L&)^)-x<) puts("");
else puts("");
}
// puts("=========================");
// for (int i=0; i<=N-1; i++) printf("%I64d %I64d\n",Query(1,i,i,i&1),Query(1,i,i,(i&1)^1));
// puts("=========================");
}
return ;
}

【Codeforces717F】Heroes of Making Magic III 线段树 + 找规律的更多相关文章

  1. W - Doom HDU - 5239 线段树 找取模的规律+求一个很大的数的平方对一个数取模的写法 特别的模数==2^63-2^31

    这个题目一开始感觉还是有点难的,这个模数这么大,根本就不知道怎么写,然后去搜了题解,知道了怎么去求当x很大的时候x的平方对一个数取模怎么样不会爆掉. 然后还顺便发现了一个规律就是当一个数更新一定次数之 ...

  2. Codeforces 717.F Heroes of Making Magic III

    F. Heroes of Making Magic III time limit per test 3 seconds memory limit per test 256 megabytes inpu ...

  3. HDU 5125 magic balls(线段树+DP)

    magic balls Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)

    题目地址:HDU 5266 这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够.那么用线段树或者RMQ维护一下区间最值就能够了.然后就是找dfs序最大 ...

  5. SPOJ GSS3 Can you answer these queries III ——线段树

    [题目分析] GSS1的基础上增加修改操作. 同理线段树即可,多写一个函数就好了. [代码] #include <cstdio> #include <cstring> #inc ...

  6. HDU 5266 pog loves szh III 线段树,lca

    Pog and Szh are playing games. Firstly Pog draw a tree on the paper. Here we define 1 as the root of ...

  7. ZOJ 3622 Magic Number 打表找规律

    A - Magic Number Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Subm ...

  8. SPOJ GSS3 Can you answer these queries III[线段树]

    SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...

  9. spoj 1557 GSS3 - Can you answer these queries III 线段树

    题目链接 给出n个数, 2种操作, 一种是将第x个数改为y, 第二种是询问区间[x,y]内的最大连续子区间. 开4个数组, 一个是区间和, 一个是区间最大值, 一个是后缀的最大值, 一个是前缀的最大值 ...

随机推荐

  1. js操作数组

    一.数组的声明方式: var colors = new Array();//创建数组 var colors = new Array(20);//创建20个长度的数组 var colors = new ...

  2. 有氧运动 && 无氧运动

    有氧运动也叫做有氧代谢运动,是指人体在氧气充分供应的情况下进行的体育锻炼.有氧运动的好处是:可以提升氧气的摄取量,能更好地消耗体内多余的热量.也就是说,在运动过程中,人体吸入的氧气与需求相等,达到生理 ...

  3. ORACLE查看补丁出现“OPatch failed with error code 1”

    案例场景:               在Oracle Linux Server release 5.7上安装完ORACLE 10g后,顺便将PSR(Patch Set Release)p681018 ...

  4. 如何查看Oracle客户端版本

    在实际工作中,总会遇到一些需要查看.验证ORACLE客户端版本的问题,因为一台服务器可能装了多个Oracle客户端版本:也有可能你需要知道安装的版本是32位还是64位的.如何查看Oracle客户端(O ...

  5. sql tuning advisor使用

    DB tuning advisor是创建优化任务,对某些sql数据库进行分析,并尽量给出优化建议的一个强大的数据库工具. 自己平时几乎没用过这玩意,所以来测一测用法,其实对于一些sql一筹莫展的时候跑 ...

  6. chm文件突然乱码了

    今天打开一个chm文件的帮组文档时,文档时乱码,以前可不是的哦.不知道自己干什么操作了.上网找了下解决办法. 打开cmd 输入regedit 进入注册表:找到: HKEY_CURRENT_USER\S ...

  7. 【WPF系列】基础学习-WPF设计模式概览

    引言 “设计模式”这个让程序员提起来就“酷”的东东,着实让让初学设计模式的programer自我陶醉一番.太多的经历,告诉我们“凡事都要个度,要学会适可而止”,否则过犹不及.“设计模式”也一样,切莫为 ...

  8. (转)Doxygen文档生成工具

    http://blog.csdn.net/lostaway/article/details/6446786 Doxygen 是一个支持 C/C++,以及其它多种语言的跨平台文档生成工具.如同 Java ...

  9. linux Shell脚本编码格式

    在windows下开发,写好的shell脚本,放到linux上执行,往往会因为编码格式的问题存在兼容问题: -bash: ./lbs-circle-server.sh: /bin/sh^M: bad ...

  10. C#学习笔记-图像处理篇(一)绘制公章

    上个月免费帮别人做事,就一直在服务员和程序员中来回切换,所以好多事情都弄得乱糟糟的,家里也是乱七八糟的,所以学习这一块也放了一段时间. 刚刚开始当服务员的时间看到了形形色色的人,觉得很好玩,他们每个人 ...