[CodeChef] The Street
给定两个长度为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的更多相关文章
- Codechef March Challenge 2014——The Street
The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submis ...
- AC日记——The Street codechef March challenge 2014
The Street 思路: 动态开节点线段树: 等差序列求和于取大,是两个独立的子问题: 所以,建两颗线段树分开维护: 求和:等差数列的首项和公差直接相加即可: 取大: 对于线段树每个节点储存一条斜 ...
- [CodeChef - STREETTA] The Street 李超线段树
大致题意: 给出两个序列A,B,A初始为负无穷,B初始为0,有三种操作 1.在A上区间[u,v]上加一个等差数列,取与原本A序列的最大值. 2.在B上区间[u,v]上加一个等差数列. 3.给出一个点X ...
- 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1288 Solved: 490 ...
- 申请邓白氏编码的时候总是提示 Enter a valid Street Address 怎么办?
今天要申请一个苹果开发者公司(Company)账号,然后需要邓白氏编码,然后填写企业的基本信息.其中对于Street Address认真的对照着中文翻译为如下格式: Kang Hesheng buil ...
- ACM: 限时训练题解-Street Lamps-贪心-字符串【超水】
Street Lamps Bahosain is walking in a street of N blocks. Each block is either empty or has one la ...
- Codeforce - Street Lamps
Bahosain is walking in a street of N blocks. Each block is either empty or has one lamp. If there is ...
- 【BZOJ4260】 Codechef REBXOR 可持久化Trie
看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...
- Wall Street English
1月23号,报名Wall Street English!
随机推荐
- 分享知识-快乐自己:Java常用API总结
1):java.io.BufferedReader类(用于从文件中读入一段字符:所属套件:java.io) 1. 构造函数BufferedReader(java.io.FileReader FileR ...
- 给手机发验证码 综合使用 (忘记密码处理 php发验证码 重置用户密码)
前台页面 提取手机号调用 jQuery的ajax,到发送验证码 [php] view plain copy <title>找回密码 - 2015年xxx报名系统</title> ...
- javascript通用参数判断
//判断value是小于等于max的数字function isNumberMax(value, max){ if(!isNumber(value) || !isNumber(max)){ ...
- node.js+express验证码的实现
安装ccap库 npm install ccap var ccap = require(); var captcha = ccap({ width:190, height:50, offset:30, ...
- hdu 2018 母牛的故事(简单dp)
母牛的故事 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- Java微信小程序开发_00_资源帖
1.微信小程序开发:http://blog.csdn.net/column/details/13721.html?&page=1 2.微信小程序栏目:http://blog.csdn.net/ ...
- codeforces 515C C. Drazil and Factorial(水题,贪心)
题目链接: C. Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes inpu ...
- Java进阶08 GUI
GUI(Graphical User Interface)提供了图形化的界面,允许用户以图形的方式与系统进行互动.在GUI推广之前,用户通常要以文本命令的方式来控制计算机.GUI直观的将计算机的功能呈 ...
- Web Service 之JAX-WS 与CXF实现
Web Service的实现方式有很多种,本篇介绍的是基于JAX-WS(纯Java)实现的,然后借由CXF工具生成Javabean. 第一步:创建一个Java工程,编写CalService接口,此接口 ...
- bzoj 1185 最小矩形覆盖 —— 旋转卡壳
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 枚举一条边,维护上.左.右方的点: 上方点到这条边距离最远,所以用叉积求面积维护: 左 ...