给定两个长度为n的数列A和B,开始数组A中每一项值为0,数组B中每一项值为负无穷大。接下来有m次操作:1.数组A区间加一个等差数列;2.数组B区间对一个等差数列取max;3.询问ai+bi的值。n<=1e9,m<=3e5。

这道题做了两天。。告诉我:要随着递归函数变的变量,千万不要放在全局。。

 #include <cstdio>
using namespace std; //#bug2:LL
typedef long long LL;
const LL maxn=1e9+, maxm=3e5+;
const LL INF=1ll<<;
//#bug10:INF不够大
LL n, m, op, l2s, cnt;
LL u, v, a, b, x; //注意a,b是一直不变的
LL ll, rr;
//注意值最多可以加到LL外!
struct node{
LL b1, change1; //max
LL a1;
LL a2, b2; //add
LL lc, rc;
}seg[maxm**]; inline LL abs(LL x) { return x>?x:-x; }
inline LL max(LL x, LL y) { return x>y?x:y; } void flag(LL now, LL a1, LL b1, LL a2, LL b2);
//给孩子打上标记
void push_down(LL &now, LL l, LL r, LL a, LL b){
//#bug4:忘记新建结点
if (!now) now=++cnt, seg[now].a1=-INF;
//#bug5:历史遗留问题(话说这个pushdown有点多余)
//#bug7:b值有变化。。现在更新的b值不与下传的b值相同
//更新的是目前uvab,下传的是这个结点的ab。(在下面修正)
flag(now, seg[now].a1, seg[now].a1+(r-l)*seg[now].b1,
a, a+(r-l)*b);
}
//取max,当然是标记永久化!
void flag(LL now, LL a1, LL b1, LL a2, LL b2){
//有个新来的数列的公差b,是在外面的
//如果a1,b1没有值,或者盖住,那就直接赋值
//bug#6:a1没有值的时候应该是负无穷大
if (seg[now].a1==-INF||(a1<=a2&&b1<=b2)){
seg[now].a1=a2, seg[now].b1=b;
seg[now].change1=;
return;
}
if (a1>a2&&b1>b2) return;
//那么现在必定有区间内交点
LL mid=(ll+rr)>>;
LL nowl, nowr;
if (abs(a1-a2)<abs(b1-b2)){ //交点在左边
//如果a1右半部分更小,就全部赋值(#bug7:注意下传标记!)
if (a1>a2) {
LL tmp=b; b=seg[now].b1;
//它的孩子替换成自己
//bug#9:l和r不对
nowl=ll, nowr=rr; rr=mid;
push_down(seg[now].lc, ll, mid, seg[now].a1, seg[now].b1);
rr=nowr; ll=mid+;
push_down(seg[now].rc, mid+, rr,
seg[now].a1+(mid+-nowl)*seg[now].b1, seg[now].b1);
ll=nowl;
b=tmp;
seg[now].a1=a2, seg[now].b1=b, seg[now].change1=;
}
//反之,把新数列的左半边往下传(它的孩子替换成新的)
//#bug7:忽略了等于的情况(证伪)
if (a1<=a2) { //#bug8:b不对。就是原来的
nowr=rr; rr=mid;
push_down(seg[now].lc, ll, mid, a2, b);
rr=nowr;
}
} else {
//与之前相同(它的孩子替换成新的)
if (a1>=a2) { //同bug8
//#bug9:下面的式子还是要用原来的ll
nowl=ll; ll=mid+;
push_down(seg[now].rc, mid+, rr, a2+(mid+-nowl)*b, b);
ll=nowl;
}
//同bug7(证伪)
if (a1<a2) {
LL tmp=b; b=seg[now].b1;
//它的孩子替换成自己(注意下传标记!)
nowl=ll, nowr=rr; rr=mid;
push_down(seg[now].lc, ll, mid, seg[now].a1, seg[now].b1);
rr=nowr; ll=mid+;
push_down(seg[now].rc, mid+, rr,
seg[now].a1+(mid+-nowl)*seg[now].b1, seg[now].b1);
ll=nowl;
b=tmp;
seg[now].a1=a2, seg[now].b1=b, seg[now].change1=;
}
}
}
void modify1(LL &now, LL l, LL r){
if (!now) now=++cnt, seg[now].a1=-INF; //用引用新建结点,这样空的不会被识别
l2s=a+(l-u)*b; //l这个x坐标上的l2的值
ll=l, rr=r;
LL mid=(l+r)>>;
LL nowl, nowr;
//如果修改过,必须再这里先push一下,不然flag的时候,可能会覆盖
if (seg[now].change1){
LL tmp=b; b=seg[now].b1;
//它的孩子替换成自己
nowl=ll, nowr=rr; rr=mid;
push_down(seg[now].lc, l, mid, seg[now].a1, seg[now].b1);
rr=nowr, ll=mid+;
push_down(seg[now].rc, mid+, r,
seg[now].a1+(mid+-nowl)*seg[now].b1, seg[now].b1);
ll=nowl;
b=tmp;
//#bug3:mid+1全没加 (还是mid!!)
seg[now].change1=;
}
if (l>=u&&r<=v){
//给出俩直线开始结束,修改下传结点。只要判断交点位置
flag(now, seg[now].a1, seg[now].a1+(r-l)*seg[now].b1,
l2s, l2s+(r-l)*b);
return;
}
if (mid>=u) modify1(seg[now].lc, l, mid);
if (mid<v) modify1(seg[now].rc, mid+, r);
}
//这个。。可以差分
void modify2(LL &now, LL l, LL r){
if (!now) now=++cnt, seg[now].a1=-INF; //这样空的不会被识别
l2s=a+(l-u)*b;
if (l>=u&&r<=v){
seg[now].a2+=l2s, seg[now].b2+=b;
return;
}
LL mid=(l+r)>>;
if (mid>=u) modify2(seg[now].lc, l, mid);
if (mid<v) modify2(seg[now].rc, mid+, r);
}
LL q1(LL now, LL l, LL r){ //只有当路径上全部都是-INF时,这个东西不存在
if (!now) return -INF;
LL mid=(l+r)>>, v=seg[now].a1+(x-l)*seg[now].b1;
if (mid>=x) return max(v, q1(seg[now].lc, l, mid));
else return max(v, q1(seg[now].rc, mid+, r));
}
LL q2(LL now, LL l, LL r){ //差分。。
if (!now) return ;
LL mid=(l+r)>>, v=seg[now].a2+(x-l)*seg[now].b2;
if (mid>=x) return v+q2(seg[now].lc, l, mid); //bug#1,mid>x
else return v+q2(seg[now].rc, mid+, r);
} int main(){
scanf("%lld%lld", &n, &m);
LL root=++cnt; seg[root].a1=-INF;
for (LL i=; i<m; ++i){
scanf("%lld", &op);
//这里把a看成开始,b看成公差!
if (op<) {
scanf("%lld%lld%lld%lld", &u, &v, &a, &b);
LL t=a; a=b; b=t;
}
if (op==) modify1(root, , n);
if (op==) modify2(root, , n);
if (op==){
scanf("%lld", &x);
LL query1=q1(, , n), query2=q2(, , n);
if (query1==-INF) { printf("NA\n"); continue; }
printf("%lld\n", query1+query2);
}
}
return ;
}

[CodeChef] The Street的更多相关文章

  1. Codechef March Challenge 2014——The Street

    The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submis ...

  2. AC日记——The Street codechef March challenge 2014

    The Street 思路: 动态开节点线段树: 等差序列求和于取大,是两个独立的子问题: 所以,建两颗线段树分开维护: 求和:等差数列的首项和公差直接相加即可: 取大: 对于线段树每个节点储存一条斜 ...

  3. [CodeChef - STREETTA] The Street 李超线段树

    大致题意: 给出两个序列A,B,A初始为负无穷,B初始为0,有三种操作 1.在A上区间[u,v]上加一个等差数列,取与原本A序列的最大值. 2.在B上区间[u,v]上加一个等差数列. 3.给出一个点X ...

  4. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1288  Solved: 490 ...

  5. 申请邓白氏编码的时候总是提示 Enter a valid Street Address 怎么办?

    今天要申请一个苹果开发者公司(Company)账号,然后需要邓白氏编码,然后填写企业的基本信息.其中对于Street Address认真的对照着中文翻译为如下格式: Kang Hesheng buil ...

  6. ACM: 限时训练题解-Street Lamps-贪心-字符串【超水】

    Street Lamps   Bahosain is walking in a street of N blocks. Each block is either empty or has one la ...

  7. Codeforce - Street Lamps

    Bahosain is walking in a street of N blocks. Each block is either empty or has one lamp. If there is ...

  8. 【BZOJ4260】 Codechef REBXOR 可持久化Trie

    看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...

  9. Wall Street English

    1月23号,报名Wall Street English!

随机推荐

  1. [BALTIC 2008] Grid

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1169 [算法] 首先DFS枚举出横着切的 然后二分 + 贪心即可 时间复杂度 : O ...

  2. 移动端H5 button 默认事件

    button 在移动端下会有自带的默认事件,如果不处理的话,点击按钮的时候会有自动刷新页面的效果,原因就是button的默认事件没有阻止. 所以在点击事件里面要加上 e.preventDefault( ...

  3. node-webkit开发基本步骤

    详情请查看:http://www.heiboard.com/?p=2091

  4. #include <deque>

    deque \(deque\)头文件主要包括一个双端队列容器.是一个支持在两端插入两端删除的线性储存空间,与vector和queue相似.与\(vector\)比起来,\(deque\)可以在\(O( ...

  5. bzoj 4066 简单题——KDtree(带重构)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4066 带部分重构的KDtree.就是那个替罪羊树思想的. 写了对拍,调了半天,发现忘了 re ...

  6. C++STL 库中set容器应用

    #include<iostream> #include<cstdio> #include<set> using namespace std; set<int& ...

  7. css菜鸟学习之block,inline和inline-block概念和区别

    block,inline和inline-block概念和区别   总体概念 block和inline这两个概念是简略的说法,完整确切的说应该是 block-level elements (块级元素) ...

  8. Project Web Server PSI 接口一些常用操作

    对Project Web Server进行二次开发,每天都把自己折腾到12点以后才休息,到处都是坑,研究那些烦人的PSI,国内根本查不到PSI相关的资料,对照API文档一点点谷歌资料,全部英文资料,开 ...

  9. 共有11款Python 中文分词库开源软件

    件过滤: 排序: 收录时间 | 浏览数 Python 中文分词库 Yaha "哑哈"中文分词,更快或更准确,由你来定义.通过简单定制,让分词模块更适用于你的需求. "Ya ...

  10. java 中Int和Integer区别以及相关示例

    Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入不是对象的基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrappe ...