传送门

首先通过dfs序把子树操作转化为区间操作,求最大值可以用斜率优化。

然后分个块,对每个块维护个凸包。修改时中间的打个标记,边角暴力重构;询问时中间的用斜率优化的方法求,边角的暴力求。

由于此题有绝对值,所以还要对原值取负后再维护一个凸包。。。。

时间复杂度\(O(nlogn+q \sqrt n)\)

代码很丑,感觉不是人看的。。

官方题解讲得比我好多了。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cassert>
#include<cmath>
#define LL long long
#define ldb long double
#define fr(i,x,y) for(int i=(x);i<=(y);i++)
#define rf(i,x,y) for(int i=(x);i>=(y);i--)
#define frz(i,x,y) for(int i=(x),z=y;i<=z;i++)
using namespace std;
const int N=200006;
const int M=N<<1;
const int BM=505;
int n,q,m;
int cnt,head[N],Next[M],v[M];
int a[N],b[N],c[N],d[N];
int clo,pre[N],dfn[N],ver[N]; struct data{
int x,y;
};
int bm;
void chkmax(LL &x,LL y){ if (y>x) x=y; }
int cmp1(const int &q,const int &w){ return d[q]<d[w]; }
int cmp2(const int &q,const int &w){ return -d[q]<-d[w]; }
struct blo{
int num[BM],l,r;
int inc;
LL x[BM],y[BM];
int h[BM],t,w; LL chk(LL x1,LL y1,LL x2,LL y2){
return x1*y2-x2*y1;
} void AddPoint(int i){
for(;w-1>=t&&chk(x[h[w]]-x[h[w-1]],y[h[w]]-y[h[w-1]],x[i]-x[h[w]],y[i]-y[h[w]])>=0;w--);
h[++w]=i;
} LL query(){
for(;w-1>=t&&x[h[t]]*inc+y[h[t]]<=x[h[t+1]]*inc+y[h[t+1]];t++);
return x[h[t]]*inc+y[h[t]];
} void build(){
//int bl,r=br;
t=1;w=0;
assert(r<=n);assert(r-l<=m);
fr(i,0,r-l) x[i]=d[num[i]],y[i]=1LL*c[num[i]]*d[num[i]],AddPoint(i);
} void init(){
assert(r<=n);assert(r-l<=m);assert(m<BM);
fr(i,l,r) num[i-l]=i;
sort(num,num+r-l+1,cmp1);
build();
}
}bo[BM]; struct bloo{
int num[BM],l,r;
int inc;
LL x[BM],y[BM];
int h[BM],t,w; LL chk(LL x1,LL y1,LL x2,LL y2){
return x1*y2-x2*y1;
} void AddPoint(int i){
for(;w-1>=t&&chk(x[h[w]]-x[h[w-1]],y[h[w]]-y[h[w-1]],x[i]-x[h[w]],y[i]-y[h[w]])>=0;w--);
h[++w]=i;
} LL query(){
for(;w-1>=t&&x[h[t]]*inc+y[h[t]]<=x[h[t+1]]*inc+y[h[t+1]];t++);
return x[h[t]]*inc+y[h[t]];
} void build(){
//int bl,r=br;
t=1;w=0;
assert(r<=n);assert(r-l<=m);
fr(i,0,r-l) x[i]=-d[num[i]],y[i]=-1LL*c[num[i]]*d[num[i]],AddPoint(i);
} void init(){
assert(r<=n);assert(r-l<=m);assert(m<BM);
fr(i,l,r) num[i-l]=i;
sort(num,num+r-l+1,cmp2);
build();
}
}boo[BM]; void read(int &x){
char ch=getchar();x=0;int w=0;
for(;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') w=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
if (w) x=-x;
} void add(int x,int y){
Next[++cnt]=head[x];
head[x]=cnt;
v[cnt]=y;
} void dfs(int x,int fa){
pre[x]=++clo;ver[clo]=x;
a[x]+=a[fa];b[x]+=b[fa];
for(int i=head[x];i;i=Next[i])
if (v[i]!=fa) dfs(v[i],x);
dfn[x]=clo;
} void init(){
m=sqrt(n);
fr(i,1,n) c[i]=a[ver[i]],d[i]=b[ver[i]];
bo[0].l=1;bo[0].r=m-1;bm=n/m; //not real
for(int i=m;i<=n;i+=m) bo[i/m].l=i,bo[i/m].r=i+m-1;
bo[bm].r=n;
fr(o,0,bm){
//int &l=bo[o].r,&r=bo[o].r;
boo[o].l=bo[o].l;boo[o].r=bo[o].r;
bo[o].init();boo[o].init();
}
} void incc(int l,int r,int v){
if (l/m==r/m){
fr(i,l,r) c[i]+=v;
bo[l/m].build();boo[l/m].build();
return;
}
frz(i,l,bo[l/m].r) c[i]+=v;bo[l/m].build();boo[l/m].build();
fr(i,bo[r/m].l,r) c[i]+=v;bo[r/m].build();boo[r/m].build();
frz(i,l/m+1,r/m-1) bo[i].inc+=v,boo[i].inc+=v;
} LL query(int l,int r){
LL ans=-1000000000000000000;
if (l/m==r/m){
fr(i,l,r) chkmax(ans,1LL*abs(c[i]+bo[l/m].inc)*d[i]);
return ans;
}
frz(i,l,bo[l/m].r) chkmax(ans,1LL*abs(c[i]+bo[l/m].inc)*d[i]);
fr(i,bo[r/m].l,r) chkmax(ans,1LL*abs(c[i]+bo[r/m].inc)*d[i]);
frz(i,l/m+1,r/m-1) chkmax(ans,bo[i].query()),chkmax(ans,boo[i].query());
return ans;
} int main(){
read(n);read(q);
int tp,x,y;
fr(i,2,n){
read(x);
add(x,i);add(i,x);
}
fr(i,1,n) read(a[i]);
fr(i,1,n) read(b[i]);
dfs(1,0);
fr(i,1,n) b[i]=abs(b[i]);
init();
while(q--){
read(tp);read(x);
if (tp==1){
read(y);
incc(pre[x],dfn[x],y);
} else{
printf("%lld\n",query(pre[x],dfn[x]));
}
}
return 0;
}

Codeforces 1178G. The Awesomest Vertex的更多相关文章

  1. [cf1178G]The Awesomest Vertex

    2020年论文题,这里给出了一个$o(n\log^{2}n+m\log^{3}n)$的做法,例题3即为原题 1.例题1 题面 给定$n$个一次函数$f_{i}(x)$,$m$次查询$F(x)=\max ...

  2. codeforces 459E

    codeforces 459E E. Pashmak and Graph time limit per test 1 second memory limit per test 256 megabyte ...

  3. Codeforces 734E. Anton and Tree 搜索

    E. Anton and Tree time limit per test: 3 seconds memory limit per test :256 megabytes input:standard ...

  4. Educational Codeforces Round 6 E. New Year Tree dfs+线段树

    题目链接:http://codeforces.com/contest/620/problem/E E. New Year Tree time limit per test 3 seconds memo ...

  5. Codeforces Round #381 (Div. 1) B. Alyona and a tree dfs序 二分 前缀和

    B. Alyona and a tree 题目连接: http://codeforces.com/contest/739/problem/B Description Alyona has a tree ...

  6. Codeforces Round #379 (Div. 2) E. Anton and Tree 缩点 直径

    E. Anton and Tree 题目连接: http://codeforces.com/contest/734/problem/E Description Anton is growing a t ...

  7. CodeForces 166E -Tetrahedron解题报告

    这是本人写的第一次博客,学了半年的基础C语言,初学算法,若有错误还请指正. 题目链接:http://codeforces.com/contest/166/problem/E E. Tetrahedro ...

  8. Codeforces Round #381 (Div. 2) D. Alyona and a tree 树上二分+前缀和思想

    题目链接: http://codeforces.com/contest/740/problem/D D. Alyona and a tree time limit per test2 secondsm ...

  9. CodeForces 505B Mr. Kitayuta's Colorful Graph

    Mr. Kitayuta's Colorful Graph Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d ...

随机推荐

  1. Android NDK(二) CMake构建工具进行NDK开发

    本文目录 一Androidstudio中需要的插件 二项目配置 ①build.gardle配置 ②CMakeLists.txt ③Android和Cpp的代码 ④so文件生成 ⑤so文件的位置 一.A ...

  2. 【Java】获取当前操作系统桌面路径

    //当前用户桌面 File desktopDir = FileSystemView.getFileSystemView() .getHomeDirectory(); String desktopPat ...

  3. day 23

    目录 面向对象总复习 面向对象总复习 面向过程编程思想: ​ 核心是过程,过程指的是做事情的步骤,即先干什么再干什么. ​ 基于该编程思想编程,就好比一条流水线,一种机械式的思维方式. 面向对象编程思 ...

  4. display:box和display:flex属性介绍

    1.display:box 父容器里面的box属性有box-orient|box-dirextion|box-align|box-pack|box-lines box-orient:用来确定父容器里面 ...

  5. SQL SERVER 字符串类型varchar格式转换成int类型进行排序

    日常数据分析过程中,经常会遇到排序的情况,有时会根据空字段表进行临时排序,转换数据类型 使用  ORDER BY CAST (<字段名> AS INT)  ASC 举例: SELECT I ...

  6. 隐身衣揭秘--java中继承/隐藏/覆写

    故事背景 看过<哈利·波特>的娃们,想必一定还记得电影中的“隐形斗篷”..这件隐形衣是哈利收到的圣诞礼物,也是死亡圣器中的三件套之一,它让哈利小盆友在执行任务的过程中简直是如虎添翼! 其实 ...

  7. 1.C&DataStructure引言

    使用过C++ <STD> 库的猿友们应该都觉得 C++中那些已经实现好了的数据类型封装使用让人很是舒服; 例如 vector 支持自动扩充数组,支持模板类,任何数据类型都可以 简单的管理, ...

  8. 数据结构中数组反转与STL库Algorithm中的reverse

    数组是个基本的线性数据结构,其实是内存中的一个块,我们可以通过c++的new来分配一个数组 int* a= new int[5]; 然后填数组的每个元素 a[0]=1; a[1]=2; a[2]=6; ...

  9. 渗透测试中Linux下反弹shell的认识

    最近老是觉得自己白天工作累,晚上理应休息 堕落了几天才发觉自己真垃圾,加紧向前吧. 0x00 前言 在平时渗透还是工作中经常会遇到shell反弹的情况,网上一搜反弹shell都是一大堆,但是真正遇到反 ...

  10. PHP each

    1.函数的作用:遍历数组元素 2.函数参数: @params array &$array 3.例子: <?php $arr = ['Boy','Girl']; while(list($k ...