好久没有写过数据结构题目了,果然还是太不自信。实际上就是要求统计一个式子:

  \(\sum (c[k]*p[k] - C)^{2}\)

拆开,分别统计和与平方和

\(co[k] * \sum p[k]^{2} - 2 * C * co[k] \sum p[k] + \sum C ^{2}\)

显然可以用树链剖分 + 线段树维护

平方和在区间 + 1的时候直接用 \((x + 1) ^ {2} = x^2 + 2 * x + 1\) 计算即可。

  至于不同的口味的问题,我们给每个口味都开一线段树,动态开点~听起来虽然复杂,但代码实际上超短。◕ᴗ◕。

#include <bits/stdc++.h>
using namespace std;
#define maxn 3000000
#define int long long
#define db double
int n, m, q, C, cnt, f[maxn], co[maxn], dfn[maxn];
int size[maxn], hson[maxn], top[maxn], fa[maxn];
int root[maxn], mark[maxn * ], cal[maxn * ], cal2[maxn * ], son[maxn * ][]; int read()
{
int x = , k = ;
char c; c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} struct edge
{
int cnp, to[maxn], last[maxn], head[maxn];
edge() { cnp = ; }
void add(int u, int v)
{ to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++; }
}E1; void dfs(int u)
{
size[u] = ; int mx = , hs = ;
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
fa[v] = u; dfs(v); size[u] += size[v];
if(size[v] >= mx) mx = size[v], hs = v;
}
hson[u] = hs;
} void dfs2(int u, int anc)
{
dfn[u] = ++ cnt, top[u] = anc;
if(hson[u]) dfs2(hson[u], anc);
for(int i = E1.head[u]; i; i = E1.last[i])
if(E1.to[i] != hson[u]) dfs2(E1.to[i], E1.to[i]);
} void Add(int &p, int l, int r, int x)
{
if(!p) p = ++ cnt; mark[p] += x;
cal2[p] += cal[p] * x + (r - l + ) * x * x;
cal[p] += (r - l + ) * x * ;
} void Push_down(int p, int l, int r)
{
int mid = (l + r) >> ;
if(!mark[p]) return;
Add(son[p][], l, mid, mark[p]); Add(son[p][], mid + , r, mark[p]);
mark[p] = ;
} void Push_Up(int p)
{
int l = son[p][], r = son[p][];
cal2[p] = cal2[l] + cal2[r]; cal[p] = cal[l] + cal[r];
} void Update(int &p, int l, int r, int L, int R, int x)
{
if(L > R || l > r) return;
if(!p) p = ++ cnt;
if(L <= l && R >= r) { Add(p, l, r, x); return; }
Push_down(p, l, r); int mid = (l + r) >> ;
if(L <= mid) Update(son[p][], l, mid, L, R, x);
if(R > mid) Update(son[p][], mid + , r, L, R, x);
Push_Up(p);
} void T_Update(int k, int u, int x)
{
for(; u; u = fa[top[u]])
Update(root[k], , n, dfn[top[u]], dfn[u], x);
} int Cal(int p)
{ return co[p] * co[p] * cal2[root[p]] - cal[root[p]] * C * co[p] + n * C * C; } signed main()
{
n = read(), m = read(), q = read(), C = read();
for(int i = ; i <= n; i ++) f[i] = read();
for(int i = ; i <= n; i ++) { int x = read(); E1.add(x, i); }
for(int i = ; i <= m; i ++) co[i] = read();
dfs(), dfs2(, ), cnt = m;
for(int i = ; i <= m; i ++) root[i] = i;
for(int i = ; i <= n; i ++) T_Update(f[i], i, );
for(int i = ; i <= q; i ++)
{
int opt = read();
if(opt == )
{
int x = read(), k = read();
T_Update(f[x], x, -), T_Update(f[x] = k, x, );
}
else
{
int k = read();
printf("%lf\n", (db) Cal(k) / (db) n);
}
}
return ;
}

【题解】CF#960 H-Santa's Gift的更多相关文章

  1. CF 1045 H. Self-exploration 解题报告

    CF 1045 H. Self-exploration 考虑到串的结构一定是 1...0....1....0.....1... 这样的,而\(01\)与\(10\)在转折点交替出现 首先串长一定是\( ...

  2. 【codeforces】【比赛题解】#960 CF Round #474 (Div. 1 + Div. 2, combined)

    终于打了一场CF,不知道为什么我会去打00:05的CF比赛…… 不管怎么样,这次打的很好!拿到了Div. 2选手中的第一名,成功上紫! 以后还要再接再厉! [A]Check the string 题意 ...

  3. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  4. 竞赛题解 - [CF 1080D]Olya and magical square

    Olya and magical square - 竞赛题解 借鉴了一下神犇tly的博客QwQ(还是打一下广告) 终于弄懂了 Codeforces 传送门 『题目』(直接上翻译了) 给一个边长为 \( ...

  5. 题解 CF 1372 B

    题目 传送门 题意 给出 \(n\),输出 \(a\) ,\(b\) (\(0 < a \leq b < n\)),使\(a+b=n\)且 \(\operatorname{lcm}(a,b ...

  6. 题解——CF Manthan, Codefest 18 (rated, Div. 1 + Div. 2) T5(思维)

    还是dfs? 好像自己写的有锅 过不去 看了题解修改了才过qwq #include <cstdio> #include <algorithm> #include <cst ...

  7. [题解] [CF 1250J] The Parade

    题面 题目大意: 给定一个 \(n\) , 所有军人的数量均在 \([1, n]\) 给定 \(a_i\) 代表高度为 \(i\) 的军人的个数 你要将这些军人分成 \(k\) 行, 满足下面两个条件 ...

  8. 题解 P1748 【H数】

    我来讲讲 \(dp\) 的做法 前言 昨天 \(PHY\) 大佬问我,这题怎么做?考虑到他没学过 \(set\) . \(priority_queue\) 和 \(queue\) .之后,我就想到了可 ...

  9. 题解 CF 1372A

    题目 传送门 题意 构造一个长度为n的数组,对于数组中的元素a,b,c,满足\(a+b\neq c\). 思路 直接让数组中的数全部变成1就可以了(其他数也行). 代码 /* * Author :We ...

随机推荐

  1. C++中的引用常见用法

    1.引用的内涵 引用就是给变量取外号而已. 2.四种不能使用引用的情况 void &r=x; //不能建立void类型引用 int &&r=x; //不能建立引用的引用 int ...

  2. Ruby 基础教程1-4

    1.对象 数值对象 字符串对象 数组对象,散列对象 正则表达式对象 时间对象 文件对象 符号对象 2.类 Numeric String Array Hash Regexp File Symbol 3. ...

  3. Unity2017 经典游戏开发教程 算法分析与实现 (张帆 著)

    https://meta.box.lenovo.com/link/view/82c451b41ce34e81a4b34cb46747d3d5 第1章 熟悉Unity软件的操作 第2章 打地鼠 (已看) ...

  4. Fiddler使用总结(三)

    我们知道Fiddler是位于客户端和服务器之间的代理,它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据.设置断点.调试web应用.修改请求的数据,甚至可以修改 ...

  5. 用IDEA编写spark的WordCount

    我习惯用Maven项目 所以用IDEA新建一个Maven项目 下面是pom文件 我粘上来吧 <?xml version="1.0" encoding="UTF-8& ...

  6. 《Git学习指南》学习笔记(二)

    第三章 提交究竟是什么 每次提交都会生成一个40位的散列值.只要知道散列值,我们就可以恢复到该次提交,这个操作也被称之为检出(checkout)操作. 访问权限与时间戳 Git会保存每个文件原有的访问 ...

  7. 《Effective C++》读书笔记 被你忽略的关于构造析构赋值

    如果程序员没有定义,那么编译器会默认隐式为你创建一个copy构造函数,一个copy赋值操作符,一个析构函数.另外如果你没有声明任何构造函数,编译器会为你声明一个default构造函数. 但是只有当这些 ...

  8. The Activation Function in Deep Learning 浅谈深度学习中的激活函数

    原文地址:http://www.cnblogs.com/rgvb178/p/6055213.html 版权声明:本文为博主原创文章,未经博主允许不得转载. 激活函数的作用 首先,激活函数不是真的要去激 ...

  9. Python实现个性化推荐二

    基于内容的推荐引擎是怎么工作的 基于内容的推荐系统,正如你的朋友和同事预期的那样,会考虑商品的实际属性,比如商品描述,商品名,价格等等.如果你以前从没接触过推荐系统,然后现在有人拿枪指着你的头,强迫你 ...

  10. [leetcode-748-Largest Number At Least Twice of Others]

    In a given integer array nums, there is always exactly one largest element. Find whether the largest ...