当前位置:网站首页>P4338 [ZJOI2018]历史(树剖)(暴力)
P4338 [ZJOI2018]历史(树剖)(暴力)
2022-06-11 01:30:00 【wind__whisper】
前言
有点懊恼的一个题…
并没有其他那些ZJOI那么毒瘤,看出了关键结论,但最后维护卡在log条虚边的伞兵性质上了。
解析
第一眼:感觉根本不可做啊。
冷静一下,既然它还变态的带修,一定是可以转化成比较形式化的东西的。
对每个节点考虑对答案贡献了多少次,设 s x s_x sx 表示 x 子树内权值之和, m x x mx_x mxx 表示 max ( a x , max u ∈ s o n x s u ) \max(a_x,\max_{u\in son_{x}}s_{u}) max(ax,maxu∈sonxsu),那么答案的上界显然是 s x − 1 s_x-1 sx−1,但前提是不同子树的权值必须交错出现,因此其实应该是 min ( s x − 1 , 2 ( s x − m x x ) ) \min(s_x-1,2(s_x-mx_x)) min(sx−1,2(sx−mxx)),递归的想可以发现这个结论一直都是对的。写一发暴力得到了30分,说明结论没有问题。
考虑如何快速的维护修改。
一个节点 x 收到某个儿子 son “一家独大”的制约当且仅当 2 ∗ s s o n ≥ s x + 1 2*s_{son}\ge s_x+1 2∗sson≥sx+1。显然至多存在一个这样的儿子,定义其为 h s o n x hson_x hsonx(特别的, h s o n x hson_x hsonx 可以为 x 自己), ( x , h s o n x ) (x,hson_x) (x,hsonx) 这样的边定义为实边,其他边定义为虚边。
考虑对一个节点 x + w,贡献发生改变的必然是一条返祖链。进一步,发现对于返祖链上的一条实边,其父亲端的贡献必然不会改变。然后我觉的虚实边变来变去我就不会了。
接下来,通过和树剖类似的证明 ,可以得出任意一条返祖链上的虚边最多有 log a i \log a_i logai 条。
所以暴力跳修改所有虚边的贡献即可。
实现上,树剖后开两棵线段树,一棵维护虚实边,一棵维护 s x s_x sx 即可。
时间复杂度 O ( n log n ( log n + log ∑ a i ) ) O(n\log n(\log n+\log {\sum a_i})) O(nlogn(logn+log∑ai))。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned ll
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read() {
ll x(0),f(1);char c=getchar();
while(!isdigit(c)) {
if(c=='-') f=-1;c=getchar();}
while(isdigit(c)) {
x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
const int N=4e5+100;
const int mod=1e9+7;
bool mem1;
inline ll ksm(ll x,ll k){
ll res(1);
while(k){
if(k&1) res=res*x%mod;
x=x*x%mod;
k>>=1;
}
return res;
}
int n,m;
struct seg{
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
ll sum[N<<2],laz[N<<2];
inline void pushup(int k){
sum[k]=sum[ls]+sum[rs];
}
inline void add(int k,int l,int r,ll w){
sum[k]+=(r-l+1)*w;
laz[k]+=w;
}
inline void pushdown(int k,int l,int r){
ll o=laz[k];laz[k]=0;
if(!o) return;
add(ls,l,mid,o);
add(rs,mid+1,r,o);
return;
}
void change(int k,int l,int r,int x,int y,ll w){
if(x<=l&&r<=y){
add(k,l,r,w);return;
}
pushdown(k,l,r);
if(x<=mid) change(ls,l,mid,x,y,w);
if(y>mid) change(rs,mid+1,r,x,y,w);
pushup(k);
}
int findpre(int k,int l,int r,int p){
if(!k) exit(0);
//debug("k=%d (%d %d) p=%d\n",k,l,r,p);
if(!sum[k]) return 0;
if(l==r) return l;
if(p<=mid) return findpre(ls,l,mid,p);
pushdown(k,l,r);
int o=findpre(rs,mid+1,r,p);
if(o) return o;
else return findpre(ls,l,mid,p);
}
ll ask(int k,int l,int r,int p){
if(l==r) return sum[k];
pushdown(k,l,r);
if(p<=mid) return ask(ls,l,mid,p);
else return ask(rs,mid+1,r,p);
}
}t1,t2;
//t1:s
//t2:tag
ll a[N],s[N],mx[N],ans;
int hson[N],siz[N],top[N],dep[N],fa[N],dfn[N],pos[N],tim;
bool tag[N];
vector<int>e[N];
void dfs1(int x,int f){
siz[x]=1;
dep[x]=dep[f]+1;
fa[x]=f;
s[x]=mx[x]=a[x];hson[x]=x;
for(int to:e[x]){
if(to==f) continue;
dfs1(to,x);
siz[x]+=siz[to];
s[x]+=s[to];
if(s[to]>mx[x]){
hson[x]=to;
mx[x]=s[to];
}
}
ans+=min(s[x]-1,2*(s[x]-mx[x]));
ll sh=hson[x]==x?a[x]:s[hson[x]];
if(2*sh<s[x]+1) hson[x]=0;
if(hson[x]&&hson[x]!=x) tag[hson[x]]=1;
return;
}
void dfs2(int x,int tp){
//debug("x=%d tp=%d\n",x,tp);
top[x]=tp;
dfn[++tim]=x;pos[x]=tim;
int son=0;
for(int to:e[x]){
if(to==fa[x]) continue;
if(siz[to]>siz[son]) son=to;
}
if(son) dfs2(son,tp);
for(int to:e[x]){
if(to==fa[x]||to==son) continue;
dfs2(to,to);
}
return;
}
void init(){
dfs1(1,0);
dfs2(1,1);
for(int i=1;i<=n;i++){
t1.change(1,1,n,pos[i],pos[i],s[i]);
if(i>1&&!tag[i]) t2.change(1,1,n,pos[i],pos[i],1);
//printf("i=%d hson=%d s=%lld tag=%d\n",i,hson[i],s[i],tag[i]);
}
return;
}
inline ll calc(ll s,ll mx){
return min(s-1,2*(s-mx));
}
inline void upd(int x,int w){
int ori=x;
//printf("upd: x=%d w=%d\n",x,w);
if(hson[x]!=x){
int son=hson[x];
ll sh=son?t1.ask(1,1,n,pos[son]):0,sx=t1.ask(1,1,n,pos[x]);
ans-=calc(sx,sh);
ans+=calc(sx+w,max(sh,a[x]+w));
//printf(" x=%d son=%d sh=%lld ans=%lld\n",x,son,sh,ans);
if(son&&2*sh<(sx+w)+1){
t2.change(1,1,n,pos[son],pos[son],1); hson[x]=0; } if(2*(a[x]+w)>(sx+w)+1){
hson[x]=x;
}
}
while(x){
int p=t2.findpre(1,1,n,pos[x]);
if(p==0||p<pos[top[x]]) x=fa[top[x]];
else{
x=dfn[p];
int son=hson[fa[x]];
ll sf=t1.ask(1,1,n,pos[fa[x]]),
sh=son?son==fa[x]?a[fa[x]]:t1.ask(1,1,n,pos[son]):0,sx=t1.ask(1,1,n,pos[x]);
ans-=calc(sf,sh);
ans+=calc(sf+w,max(sx+w,sh));
//printf(" x=%d son=%d sf=%lld sh=%lld sx=%lld p=%d ans=%lld\n",x,son,sf,sh,sx,p,ans);
if(son&&2*sh<(sf+w)+1){
t2.change(1,1,n,pos[son],pos[son],1);
hson[fa[x]]=0;
}
if(2*(sx+w)>=(sf+w)+1){
t2.change(1,1,n,pos[x],pos[x],-1);
hson[fa[x]]=x;
}
x=fa[x];
}
}
x=ori;
a[x]+=w;
while(x){
t1.change(1,1,n,pos[top[x]],pos[x],w);
x=fa[top[x]];
}
return;
}
bool mem2;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
e[x].push_back(y);
e[y].push_back(x);
}
init();
printf("%lld\n",ans);
for(int i=1;i<=m;i++){
int x=read(),w=read();
upd(x,w);
printf("%lld\n",ans);
}
return 0;
}
/* */
边栏推荐
- Project records
- The annual salary of testers in large factories ranges from 300000 to 8K a month. Roast complained that the salary was too low, but he was ridiculed by netizens?
- Merge sort ()
- 贵金属白银行情走势图缘何强势?
- Md61 plan independent demand import Bapi [by daily dimension / dynamic template / dynamic field]
- clang-format 最全格式说明
- 421. maximum XOR value of two numbers in the array
- [3.delphi common components] 6 scroll bar
- Analysis of the difficulties in the architecture design of massive chat messages in the live broadcast room
- [3.delphi common components] 8 dialog box
猜你喜欢

当逻辑删除遇上唯一索引,遇到的问题和解决方案?

CRS-4544 & ORA-09925

Li Kou brushing questions - hash table

Fb02 edit coding block field

14: 00 interview, came out at 14:08, the question is really too

378. 有序矩阵中第 K 小的元素

SSH配置密钥登录时需要注意私钥是否设置了密码(passphrase)

叶酸配体的金属有机骨架材料MOFs负载5-氟尿嘧啶,西达本胺,紫杉醇,阿霉素,柔红霉素,布洛芬,喜树碱,姜黄素,藤黄酸等小分子药物

NFT Insider #61:Animoca Brands 在 340 项投资中持有 15 亿美元的加密资产

2022 high altitude installation, maintenance and removal of simulated examination platform of theoretical question bank
随机推荐
腾讯测试开发岗面试上机编程题
Implementing queues with stacks
3P5 Industrial Engineering Lecture 1-2: Method of Study
渗透测试-安全服务体系+OWASP top 10
[3.delphi common components] 4 Select class component
优化调度(火电、风能、储能)【matlab代码实现】
koa2学习笔记
The diligent is the laziest
Epoll principle and Application & ET mode and lt mode
Is it appropriate for a 27 - year-old girl to change her career from zero to software testing?
ME11/ME12采购信息记录及条件记录创建及更新BAPI:ME_INFORECORD_MAINTAIN_MULTI
从测试零基础到测试架构师,这10年,他是这样让自己成才的
Binary tree sequence traversal
clang-format 最全格式说明
Core principle and code explanation of epoll reactor model
Internet of things final assignment - sleep quality detection system (refined version)
adb 常用命令解析
SQL | 外连接
Why is the trend chart of precious metal silver strong?
2022 safety officer-a certificate special operation certificate examination question bank and simulation examination