[2018-9-4T2]探索黑暗dark
题目大意:有一棵树,第$i$个点的点权为$s_i(s_1>0)$。初始有每个点都是亮的。$m$次修改,每次改变一个点的亮暗,回答包含$1$的全亮的连通块中点权和最大的连通块的和的值。
题解:正解不怎么会(我只打了一遍代码),这里是$97$分代码(复杂度$O(n^2log_2n)$,暴力复杂度$O(n^2)$,但是就是$97$。。。)(其实我只是想记录一下我考试的时候写的东西而已,没有任何参考价值)
第一次看题目的时候,把题目理解成了“在$1$所在的连通块中选出一些数,使它们最大”。这不是树剖+线段树+小$DP$吗?
令$w_u=\sum\limits_{v\in u的子树}(s_i\times[s_i>0])$,这可以$O(n)$求出。每次修改一个点$u$,找到它的父亲中第一个暗的(记为$f$)(对于树剖出来的每一条链的时间复杂度是$O(\log_2n)$的),把$w_{[f,u)}$都加上/减去$w_u$值(对于每一条链的时间复杂度也是$O(\log_2n)$的),在输出$w_1$就行了,总复杂度$O(n\log_2^2n)$(挺正常的呀)。
于是我兴冲冲地打了个代码,样例$1$过了(毕竟小样例一般都很简单),我没注意到大样例,就去写$T1$了。
离考试结束还有$30min-$的时候,我回来看了一下$T2$,发现有大样例,于是测了一下,果不其然的挂了,发现题目好像理解错了$QAQ$,开始改。
发现这样的话,对于区间$[f,u)$,若修改后的$w_{i,i\in [f,u)}\leqslant0$,就不会对上面产生贡献,就要$break$掉,而且不一定每一个值都加上/减去了$w_u$(修改前和修改后的$w_i$符号不相等,向上的贡献就会变化),似乎很麻烦。
于是我就记录一下区间的最小值,来判断这个区间是否有会有变号或者不会对上方产生贡献的点的点,修改这个区间,更改一下修改的值,继续操作,直到左端点不亮或者修改前后都小于零
这样,每次修改区间就有$O(n)$个,对于每个区间复杂度$O(\log_2n)$,但是想到这种题目肯定是随机数据(反正一般想不到这比暴力还劣的做法,也就没人卡),限制点的个数一定很少(区间少),于是信仰一交,发现是过了(考试的时候少写一句话没调出来,考试后调的)。
卡点:1.修改区间时,下一个区间的右端点求错(应该是 fa[f] ,写成 fa[dfn[f]] )。
C++ Code:($97$分)
#include <cstdio>
#define maxn 100010
const long long inf = 0x7fffffffffffffff; int n, m;
long long w[maxn], W[maxn], ANS; int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
void addE(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
} inline long long max(long long a, long long b) {return a > b ? a : b;}
inline long long min(long long a, long long b) {return a < b ? a : b;} namespace ST {
long long tg[maxn << 2], mn[maxn << 2];
bool V[maxn << 2];
inline void update(int rt) {
mn[rt] = min(mn[rt << 1], mn[rt << 1 | 1]);
}
void build(int rt, int l, int r) {
V[rt] = true;
if (l == r) {
mn[rt] = w[l];
return ;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
update(rt);
}
inline void pushdown(int rt) {
long long &x = tg[rt];
tg[rt << 1] += x;
tg[rt << 1 | 1] += x;
mn[rt << 1] += x;
mn[rt << 1 | 1] += x;
x = 0;
}
int L, R;
long long num;
void Add(int rt, int l, int r) {
if (L <= l && R >= r) {
mn[rt] += num;
tg[rt] += num;
return ;
}
int mid = l + r >> 1;
if (tg[rt]) pushdown(rt);
if (L <= mid) Add(rt << 1, l, mid);
if (R > mid) Add(rt << 1 | 1, mid + 1, r);
update(rt);
}
void add(int ll, int rr, long long Num) {
L = ll;
R = rr;
num = Num;
Add(1, 1, n);
}
bool modify(int rt, int l, int r, int p) {
if (l == r) return V[rt] = !V[rt];
int mid = l + r >> 1;
bool ans;
if (p <= mid) ans = modify(rt << 1, l, mid, p);
else ans = modify(rt << 1 | 1, mid + 1, r, p);
V[rt] = V[rt << 1] && V[rt << 1 | 1];
return ans;
}
int p;
long long ask(int rt, int l, int r) {
if (l == r) return tg[rt] + w[p];
int mid = l + r >> 1;
if (tg[rt]) pushdown(rt);
if (p <= mid) return ask(rt << 1, l, mid);
else return ask(rt << 1 | 1, mid + 1, r);
}
long long ask(int P) {
p = P;
return ask(1, 1, n);
}
int ans;
bool Query(int rt, int l, int r) {
if (V[rt] && (min(mn[rt], mn[rt] + num) >= 0)) return false;
if (l == r) {
ANS = min(mn[rt] + num, mn[rt]);
if (!V[rt]) ANS = inf;
ans = l;
return true;
}
// if (L <= l && R >= r) return V[rt];
if (tg[rt]) pushdown(rt);
int mid = l + r >> 1;
if (R > mid) if (Query(rt << 1 | 1, mid + 1, r)) return true;
if (L <= mid) if (Query(rt << 1, l, mid)) return true;
return false;
}
int query(int ll, int rr, long long Num) {
L = ll, R = rr, num = Num;
if (Query(1, 1, n)) return ans;
else return ll - 1;
}
} int dfn[maxn], idx, top[maxn], son[maxn];
int dep[maxn], fa[maxn], sz[maxn], ret[maxn];
void dfs1(int u) {
sz[u] = 1;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
sz[u] += sz[v];
if (!son[u] || sz[v] > sz[son[u]]) son[u] = v;
}
}
}
void dfs2(int u) {
dfn[u] = ++idx;
ret[idx] = u;
int v = son[u];
if (v) top[v] = top[u], dfs2(v);
for (int i = head[u]; i; i = e[i].nxt) {
v = e[i].to;
if (v != fa[u] && v != son[u]) {
top[v] = v;
dfs2(v);
}
}
} void dfs(int rt) {
// W[rt] = max(0, w[rt]);
W[rt] = w[rt];
for (int i = head[rt]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[rt]) {
dfs(v);
W[rt] = max(W[rt], W[rt] + W[v]);
}
}
} void modify(int x) {
bool o = ST::modify(1, 1, n, dfn[x]);
long long op = ST::ask(dfn[x]);
if (op <= 0) return ;
op *= (o ? 1ll : -1ll);
// printf("op:%lld\n", op);
x = fa[x];
while (x) {
int tmp = ST::query(dfn[top[x]], dfn[x], op);
if (tmp != dfn[top[x]] - 1) {
ST::add(tmp, dfn[x], op);
if (ANS == inf) break;
if (op < 0) {
op = op - ANS;
if (op >= 0) break;
} else {
op = op + ANS;
if (op <= 0) break;
}
x = fa[ret[tmp]];
} else {
ST::add(tmp + 1, dfn[x], op);
x = fa[top[x]];
}
}
// puts("over");
} int main() {
scanf("%d%d", &n, &m);
for (int i = 2; i <= n; i++) {
int a;
scanf("%d", &a);
addE(a, i);
addE(i, a);
}
dep[top[1] = 1] = 1;
dfs1(1);
dfs2(1);
for (int i = 1; i <= n; i++) scanf("%lld", w + i);
// for (int i = 1; i <= n; i++) printf("%lld ", dfn[i]); puts("");
dfs(1);
for (int i = 1; i <= n; i++) w[dfn[i]] = W[i];
ST::build(1, 1, n);
while (m --> 0) {
int a;
scanf("%d", &a);
modify(a);
printf("%lld\n", ST::ask(dfn[1]));
// for (int i = 1; i <= n; i++) printf("%lld ", ST::ask(dfn[i])); puts("");
}
return 0;
}
卡点:无
C++ Code:($100$分)
#include <cstdio>
#define maxn 100010
const long long inf = 0x3f3f3f3f3f3f3f3f; int n, m;
long long w[maxn], ANS, now[maxn], sum[maxn];;
bool vis[maxn]; int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
void addE(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
} inline long long max(long long a, long long b) {return a > b ? a : b;}
inline long long min(long long a, long long b) {return a < b ? a : b;} namespace ST {
struct node {
long long a, b;
node(long long _a = 0, long long _b = 0) {a = _a, b = _b;}
inline node operator + (const node &rhs) {
return (node) {max(a + rhs.a, -inf), max(b + rhs.a, rhs.b)};
}
inline long long mx() {return max(a, b);}
} V[maxn << 2];
inline void update(int rt) {
V[rt] = V[rt << 1 | 1] + V[rt << 1]; //因为右节点深度深,是右节点转移到左节点
}
int L, R, p;
node num;
void add(int rt, int l, int r) {
if (l == r) {
V[rt] = num;
return ;
}
int mid = l + r >> 1;
if (p > mid) add(rt << 1 | 1, mid + 1, r);
else add(rt << 1, l, mid);
update(rt);
}
void add(int pos, node Num) {
p = pos;
num = Num;
add(1, 1, n);
}
node ask(int rt, int l, int r) {
if (L <= l && R >= r) return V[rt];
int mid = l + r >> 1;
node ans;
// printf("%d %d %d\n", rt, l, r);
if (R > mid) ans = ask(rt << 1 | 1, mid + 1, r);
if (L <= mid) ans = ans + ask(rt << 1, l, mid);
return ans;
}
node ask(int ll, int rr) {
L = ll;
R = rr;
// printf("%d %d\n", L, R);
return ask(1, 1, n);
}
} int dfn[maxn], idx, top[maxn], son[maxn], down[maxn];
int dep[maxn], fa[maxn], sz[maxn], ret[maxn];
void dfs1(int u) {
sz[u] = 1;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
sz[u] += sz[v];
if (!son[u] || sz[v] > sz[son[u]]) son[u] = v;
}
}
}
void dfs2(int u) {
dfn[u] = ++idx; down[u] = u;
int v = son[u];
if (v) top[v] = top[u], dfs2(v), down[u] = down[v];
for (int i = head[u]; i; i = e[i].nxt) {
v = e[i].to;
if (v != fa[u] && v != son[u]) {
top[v] = v;
dfs2(v);
}
}
}
void modify(int x) {
long long tmp6 = vis[x] ? -inf : w[x], op = tmp6 - now[x]; now[x] = tmp6;
vis[x] ^= 1;
// printf("op:%lld\n", op);
while (top[x] != 1) {
sum[x] += op;
long long tmp = ST::ask(dfn[top[x]], dfn[down[x]]).mx();
ST::add(dfn[x], ST::node(sum[x]));
tmp = ST::ask(dfn[top[x]], dfn[down[x]]).mx() - tmp;
op = tmp;
x =fa[top[x]];
}
sum[x] += op;
ST::add(dfn[x], ST::node(sum[x]));
// puts("over");
} int main() {
// freopen("dark.in", "r", stdin);
// freopen("dark.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 2; i <= n; i++) {
int a;
scanf("%d", &a);
addE(a, i);
addE(i, a);
}
dep[top[1] = 1] = 1;
dfs1(1);
dfs2(1);
// for (int i = 1; i <= n; i++) printf("%lld ", dfn[i]); puts("");
// dfs(1);
for (int i = 1; i <= n; i++) {
scanf("%lld", w + i);
modify(i);
vis[i] = true;
}
while (m --> 0) {
int a;
scanf("%d", &a);
modify(a);
printf("%lld\n", ST::ask(dfn[1], dfn[down[1]]).mx());
// for (int i = 1; i <= n; i++) printf("%lld ", ST::ask(dfn[i])); puts("");
}
return 0;
}
[2018-9-4T2]探索黑暗dark的更多相关文章
- 2018年年度总结 & 2019年计划
2018关键词 「探索」 引用以前作文最爱写的开头,时间如白驹过隙,回想上次写17年年度总结,仿佛也就过了几日光景. 首先回顾一下17年定下的目标, 18年我将关键字设为探索,目的有两个,一是 ...
- 2017年年度总结 & 2018年计划
2017年年度总结 & 2018年计划 2017关键词 「入门」 从2017年4月,入坑软件测试行业,感谢这10个月,给予我开发.测试帮助的前辈们. 这10个月以来, 1,前后花了一个 ...
- VR外包商:最新WEARVR游戏下载
WEARVR每周下载Top10——第二弹 还在为寻找好玩的VR游戏而烦恼吗?我们有来自WEARVRapp市场(一个虚拟现实体验的跨平台仓库)上周下载排行榜前十的游戏. 10. Stunt Kart ...
- SFC游戏列表(维基百科)
SFC游戏列表 日文名 中文译名 英文版名 发行日期 发行商 スーパーマリオワールド 超级马里奥世界 Super Mario World 1990年11月21日 任天堂 エフゼロ F-Zero F-Z ...
- 敏捷社区--敏捷与OKR
携程敏捷总动员是由携程技术管理中心(PMO)发起的敏捷项目管理线下主题沙龙活动(每2月一次),旨在和研发管理同行分享互联网行业第一线的优秀敏捷实践. 5月10日携程敏捷总动员-OKR专场活动, ...
- Newton's Dark Secrets《牛顿探索》
1643年1月4日,在英格兰林肯郡小镇沃尔索浦的一个自耕农家庭里,牛顿诞生了.牛顿是一个早产儿,出生时只有三磅重,接生婆和他的亲人都担心他能否活下来.谁也没有料到这个看起来微不足道的小东西会成为了一位 ...
- 2018中国(深圳)IT领袖峰会马化腾演讲全文《数字中国的机遇与探索》
我们今天大会的主题是数字中国,也佩服我们吴鹰主席在十年前就想到发展的趋势,这么早就把我们联合会取名数字中国.昨天有一个闭门会议,有相当大的篇幅大家都谈了科技.谈创新,大家觉得科技的威力和优势越来越明显 ...
- CHAPTER 8 Out of Darkness 第8章 走出黑暗
CHAPTER 8 Out of Darkness 第8章 走出黑暗 We expect scientists to be trying to discover new things, and for ...
- 微信小程序想要的是无法监测的流量dark social
“微信小程序”将带来什么样的变化?就单单的是一个超级Web app?还是只是为了给大家手机节省一些空间?腾讯想要的是高达70%以上的“无法监测的巨大流量”,称之为“dark social”(暗社交). ...
随机推荐
- ReactiveCocoa实战: 模仿 "花瓣",重写 LeanCloud Rest Api的iOS REST Client.
这一次我们将要讨论的是移动开发中比较重要的一环--网络请求的封装.鉴于个人经验有限,本文将在一定程度上参考 基于AFNetworking2.0和ReactiveCocoa2.1的iOS REST Cl ...
- iOS提示框,为什么你应该使用 MBProgressHUD?
这是一篇带有一定笔者主观感情色彩的比较文章.文章着重对比github上最流行的两个iOS进度提示控件 MBProgressHUD 与 SVProgressHUD的各自优劣,来帮助初学者找到一个适合的i ...
- 基于mybatis设计简单OA系统问题1
全类名与全路径 全类名是某个文件在项目中的位置,格式为包名.类名 路径分为相对路径和绝对路径. 绝对路径是指这个文件在操作系统中的位置, 相对路径通过这个文件的上一级 ./ 或下一级/ 来指定文件 ...
- ajaxfileupload多文件上传 - 修复只支持单个文件上传的bug
搜索: jquery ajaxFileUpload AjaxFileUpload同时上传多个文件 原生的AjaxFileUpload插件是不支持多文件上传的,通过修改AjaxFileUpload少量代 ...
- 简单了解一下oracle中的显示游标和存储过程
游标 游标主要分两类动态和静态游标,静态游标是编译时知道明确的select语句的游标,静态游标分类两种,显示游标和静态游标,这里只说显示游标 显示游标 declare name emp.ename%t ...
- React路由-进阶篇
路由进阶 1.多级路由,和之前的思想一样,在子路由里面继续写Route,继续挂载组件,就可以实现多级路由 比如这样:class Food extends Component{ render() { r ...
- php-5.6.26源代码 - 扩展模块的加载、注册
// main实现在文件 php-5.6.26\sapi\cgi\cgi_main.c int main(int argc, char *argv[]) { .... cgi_sapi_module- ...
- 【yii2】rules规则的默认值
ExampleModel.php /** * {@inheritdoc} */ public function rules() { return [ ['updated_at','default',' ...
- P1414 又是毕业季II (数学?
题目背景 “叮铃铃铃”,随着高考最后一科结考铃声的敲响,三年青春时光顿时凝固于此刻.毕业的欣喜怎敌那离别的不舍,憧憬着未来仍毋忘逝去的歌.1000多个日夜的欢笑和泪水,全凝聚在毕业晚会上,相信,这一定 ...
- 17-比赛1 F - 较小元素 Weak in the Middle (set)
Seg-El has last chance to make the final changes in order to prevent the destruction of Krypton. He ...