[集训]Evocation
题意
一颗有根树,每个点有黑白两种颜色和阀值ai,若它的子树中(不包括自己)的黑色数量大于ai,则产生一点贡献。每次将一个点的颜色取反,求每次修改后的贡献。n,q<=1E5。
思考
树剖后直接分块就行了。复杂度约为O((n+q)sqrt(nlogn)),但似乎更小?
代码
#pragma GCC optimize 2
#include<bits/stdc++.h>
using namespace std;
const int maxn=1E5+;
///////////////////////////////////////////////////////////////////////////////
int wait[maxn],wait_R[maxn],wait_C[maxn],wait_W[maxn];
template<class T>inline void copy(T*A,T*B,int l,int r)
{
for(int i=l;i<=r;++i)
A[i-l+]=B[i];
}
struct block
{
int n,pos,layer,now;
bool created;
int*f,*c;
block()
{
created=now=;
}
void init(int x,int where,int*A)
{
if(created)
delete f,delete c;
created=;
for(int i=;i<=x;++i)
wait_R[i]=A[i],wait_C[i]=;
sort(wait_R+,wait_R+x+);
int size=;
for(int i=;i<=x;++i)
{
if(wait_R[i]!=wait_R[i-]||i==)
wait_W[++size]=wait_R[i];
++wait_C[size];
}
n=size;
f=new int[n+];
c=new int[n+];
now=c[]=f[]=c[n+]=f[n+]=;
layer=where;
pos=;
for(int i=;i<=n;++i)
f[i]=wait_W[i],c[i]=wait_C[i];
while(f[pos]<layer)
now+=c[pos],++pos;
}
inline int get()
{
return now;
}
inline void add()
{
if(layer+==f[pos]+)
now+=c[pos],++pos;
++layer;
}
inline void remove()
{
if(pos&&layer-==f[pos-])
now-=c[pos-],--pos;
--layer;
}
};
struct sequence
{
int*a,*tag,*bel,*tail;
block*B;
int n,sqr,tot;
void init(int x,int*A)
{
n=x;
sqr=sqrt(n+0.5);
a=new int[n+];
bel=new int[n+];
tag=new int[sqr+];
tail=new int[sqr+];
for(int i=;i<=sqr+;++i)
tail[i]=tag[i]=;
a[]=;
for(int i=;i<=n;++i)
a[i]=A[i];
int L=,R=sqr;
B=new block[sqr+];
tot=;
while(L<=n)
{
int len=min(n,R)-L+;
copy(wait,a,L,min(n,R));
B[++tot].init(len,,wait);
for(int i=L;i<=R;++i)
bel[i]=tot;
tail[tot]=min(n,R);
L+=sqr,R+=sqr;
}
}
inline int get()
{
int sum=;
for(int i=;i<=tot;++i)
sum+=B[i].now;
return sum;
}
inline void add(int x)
{
int i=;
for(i=;bel[i]!=bel[x];i+=sqr)
B[bel[i]].add();
int L=i,R=tail[bel[x]];
int len=R-L+;
for(int i=L;i<=R;++i)
wait[i-L+]=a[i]-B[bel[x]].layer;
for(int i=L;i<=x;++i)
--wait[i-L+];
for(int i=L;i<=R;++i)
a[i]=wait[i-L+];
B[bel[x]].init(len,,wait);
}
inline void remove(int x)
{
int i=;
for(i=;bel[i]!=bel[x];i+=sqr)
B[bel[i]].remove();
int L=i,R=tail[bel[x]];
int len=R-L+;
for(int i=L;i<=R;++i)
wait[i-L+]=a[i]-B[bel[x]].layer;
for(int i=L;i<=x;++i)
++wait[i-L+];
for(int i=L;i<=R;++i)
a[i]=wait[i-L+];
B[bel[x]].init(len,,wait);
}
inline void addDot(int x,int y)
{
int i=;
while(bel[i]!=bel[x])
i+=sqr;
int L=i,R=tail[bel[x]];
int len=R-L+;
for(int i=L;i<=R;++i)
wait[i-L+]=a[i]-B[bel[x]].layer;
wait[x-L+]+=y;
for(int i=L;i<=R;++i)
a[i]=wait[i-L+];
B[bel[x]].init(len,,wait);
}
}S[maxn];
///////////////////////////////////////////////////////////////////////////////
int n,q,a[maxn];
int size,head[maxn*];
int sum[maxn],fa[maxn],son[maxn],top[maxn],where[maxn],dfn[maxn],low[maxn],ti;
int tot,ans;
bool c[maxn];
struct edge
{
int to,next;
}E[maxn*];
void dfs1(int u,int F)
{
fa[u]=F,sum[u]=;
for(int i=head[u];i;i=E[i].next)
{
int v=E[i].to;
if(v==F)
continue;
dfs1(v,u);
sum[u]+=sum[v];
if(sum[son[u]]<sum[v])
son[u]=v;
}
}
void dfs2(int u,int F)
{
low[u]=dfn[u]=++ti;
if(son[F]==u)
top[u]=top[F];
else
top[u]=u;
if(son[u])
{
dfs2(son[u],u);
low[u]=low[son[u]];
}
for(int i=head[u];i;i=E[i].next)
{
int v=E[i].to;
if(v==F||v==son[u])
continue;
dfs2(v,u);
low[u]=low[v];
}
}
void get(int u)
{
wait[where[u]=++tot]=a[u];
if(son[u])
get(son[u]);
}
void add(int u,int v)
{
E[++size].to=v;
E[size].next=head[u];
head[u]=size;
}
void addChain(int x)
{
while(x)
{
S[top[x]].add(where[x]);
x=fa[top[x]];
}
}
void removeChain(int x)
{
while(x)
{
S[top[x]].remove(where[x]);
x=fa[top[x]];
}
}
int askChain(int x)
{
int sum=;
while(x)
{
sum+=S[top[x]].get();
x=fa[top[x]];
}
return sum;
}
///////////////////////////////////////////////////////////////////////////////
int main()
{
ios::sync_with_stdio(false);
int num;
cin>>num;
cin>>n>>q;
for(int i=;i<=n;++i)
{
int x;
cin>>x;
add(x,i);
add(i,x);
}
for(int i=;i<=n;++i)
cin>>a[i];
dfs1(,);
dfs2(,);
fa[]=;
for(int u=;u<=n;++u)
if(top[u]==u)
{
tot=;
get(u);
S[u].init(tot,wait);
}
while(q--)
{
int x;
cin>>x;
if(c[x])
{
int last=askChain(x);
removeChain(fa[x]);
S[top[x]].addDot(where[x],-);
int now=askChain(x);
ans+=now-last;
}
else
{
int last=askChain(x);
addChain(fa[x]);
S[top[x]].addDot(where[x],);
int now=askChain(x);
ans+=now-last;
}
c[x]^=;
cout<<ans<<" ";
}
return ;
}
[集训]Evocation的更多相关文章
- QDEZ集训笔记【更新中】
这是一个绝妙的比喻,如果青岛二中的台阶上每级站一只平度一中的猫,差不多站满了吧 自己的理解 [2016-12-31] [主席树] http://www.cnblogs.com/candy99/p/61 ...
- 2015UESTC 暑假集训总结
day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...
- JS省队集训记
不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...
- 2013ACM暑假集训总结-致将走上大三征途的我
回想起这个暑假,从开始与雄鹰一起的纠结要不要进集训队,与吉吉博博组队参加地大邀请赛,害怕进不了集训队.当时激励我月份开始接触的,记得当时在弄运动会来着,然后就问了雄鹰一些输入输出的东西,怀着满心的期待 ...
- 至芯FPGA培训中心-1天FPGA设计集训(赠送FPGA开发板)
至芯FPGA培训中心-1天FPGA设计集训(赠送开发板) 开课时间2014年5月3日 课程介绍 FPGA设计初级培训班是针对于FPGA设计技术初学者的课程.课程不仅是对FPGA结构资源和设计流程的描述 ...
- 2014年CCNU-ACM暑期集训总结
2014年CCNU-ACM暑期集训总结 那个本期待已久的暑期集训居然就这种.溜走了.让自己有点措手不及.很多其它的是对自己的疑问.自己是否能在ACM这个领域有所成就.带着这个疑问,先对这个暑假做个总结 ...
- [补档] 大假期集训Part.1
新博客搭起来先补一发档... 那就从大假期集训第一部分说起好了QwQ 自己还是太菜掉回了2016级水平 day1: day1的时候来得有点晚(毕竟准高一)然后进机房发现早就开考了还没有给我题面于是搞了 ...
- [补档]暑假集训D6总结
考试 不是爆零,胜似爆零= = 三道题,就拿了20分,根本没法玩好吧= = 本来以为打了道正解,打了道暴力,加上个特判分,应该不会死的太惨,然而--为啥我只有特判分啊- - 真的是惨. 讲完题觉得题是 ...
- [补档]暑假集训D5总结
%dalao 今天又有dalao来讲课,讲的是网络流 网络流--从入门到放弃:7-29dalao讲课笔记--https://hzoi-mafia.github.io/2017/07/29/27/ ...
随机推荐
- MySQL Server逻辑架构
1.MySQL基础 MySQL是一个开放源代码的关系数据库管理系统.原开发者为瑞典的MySQL AB公司,最早是在2001年MySQL3.23进入到管理员的视野并在之后获得广泛的应用. 2008年My ...
- slim中的参数获取
官方文档中对于get和post的参数有以下获取方式 $app->get('/', function (Request $req, Response $res, $args = []) { $my ...
- POJ 2976 Dropping tests [二分]
1.题意:同poj3111,给出一组N个有价值a,重量b的物品,问去除K个之后,剩下的物品的平均值最大能取到多少? 2.分析:二分平均值,注意是去除K个,也就是选取N-K个 3.代码: # inclu ...
- HMaster/HRegion Server 工作原理
1.HBase系统架构 2. HRegion Sever架构图 0.94之前的版本 0.96+的版本 WAL: 即Write Ahead Log, 是HDFS上一个文件,早期版本中称为 ...
- python的一些高阶用法
map的用法 def fn(x): return x*2 L1 = [1,2,3,4,5,6] L2 = list(map(fn,L1)) L2 [2, 4, 6, 8, 10, 12] 通过上面的运 ...
- 1027 打印沙漏 (20 分)C语言
题目描述 本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个"*",要求按下列格式打印 ***** *** * *** ***** 所谓"沙漏形状" ...
- 1042 字符统计 (20 分)C语言
请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过 1000 的字符串.字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个英文字母, ...
- webpack实践——DLLPlugin 和 DLLReferencePlugin的使用
DLLPlugin 和 DLLReferencePlugin的使用 DLLPlugin 和 DLLReferencePlugin 用某种方法实现了拆分 bundles,同时还大大提升了构建的速度. 1 ...
- Yolo V3理解bbox和label的关系
假如一个bbox坐标为:[35 220 62 293 3] 第一步:将bbox转换为中心坐标和宽高形式(3种缩放比例进行缩放) 那么onehot:[0 0 0 1 0 0 0 0 0 0 ...... ...
- Spring--2.Spring之IOC--了解IOC容器
IOC(容器),用来集成别的框架 1.IOC(Inversion(反转)Of Control):控制反转 控制:资源的获取方式: 主动式: BookServlet{ BookService bs=ne ...