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

  \(\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. 怎么判断ThreadPool线程池里的任务都执行完毕

    在下面 链接中做方便的应该是第三种方法(他也推荐了),但是第三种方法有个小问题,就是 : WaitHandle.WaitAll(_ManualEvents); 中的_ManualEvents最大为64 ...

  2. hive中的优化问题

    一.fetch抓取 fetch 抓取是指,hive中对某些情况的查询可以不必使用MapReduce计算.(1)把hive.fetch.task.conversion 设置成none,然后执行查询语句, ...

  3. hdu1257最少拦截系统(暴力)

    最少拦截系统 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  4. Unity操作小技巧

    1.操作类 1)F:选择物体后聚焦 2)V:选择物体的顶点,顶点吸附 3)Ctrl:摁住后拖动物体,可以按照系统设置的步长进行移动(Edit -> Snap setting) 4)Q W E R ...

  5. Java and SDK 环境变量设置

    File comes from http://www.cnblogs.com/shinge/p/5500002.html JAVA环境变量配置详解 JAVA环境变量JAVA_HOME.CLASSPAT ...

  6. 流畅的python(笔记)

    流畅的python中有很多奇技淫巧,整本书都在强调如何最大限度地利用Python 标准库.介绍了很多python的不常用的数据类型.操作.库等,对于入门python后想要提升对python的认识应该有 ...

  7. lintcode671 循环单词

    循环单词   The words are same rotate words if rotate the word to the right by loop, and get another. Cou ...

  8. ionic LoadingController 模块使用

    html 代码: <ion-header> <ion-navbar> <ion-title>Loading</ion-title> </ion-n ...

  9. 理解 JavaScript 原型 / 原型链

    关于对象 以下代码中 p 的值是一个新对象,里面拥有 name 和 age 属性 function People(name, age){ this.name = name this.age = age ...

  10. solidity中的memory和 storage详解

    Solidity是一种智能合约高级语言,运行在Ethereum虚拟机(EVM)之上.这里我会讲解一下关键字storage和memory的区别. storage的结构是在合约部署创建时,根据你的合约中状 ...