还是太菜了,码力小,很多题都不会做
前言
春节打的比赛
本来可以上紫了,迷之跳过C掉了分QAQ
比赛过程:
看完A,觉得太水不科学,多看了几次。。
看完B,觉得太水不科学,多看了几次。。
然后看了E不会做
看了D不是很看得懂
看了F好像有搞头
看了C,看了半天没看到题面有输出任意一组解的意思,T2都有ans of them。。
然后觉得理解错题意了。。
就跳过了
开始刚F
刚啊刚
过了样例
WA了pre3,手出数据
过了pre3,WA了pre6
写个对拍,终于过了
比赛还有十多分钟
闲逛了一下
决定做C
但是感觉题意还是理解不对
看看时间还有5分钟
决定随便打一打。。
于是打了三分钟。。
样例都不管就交了。。
发现WApre3
早上发现是-1点
判了-1就A了
哇,这是什么东西啊。。
C题三分钟的题没有做。。
做了个只有89个人做的F
C题当时也有1200+分的,我的F也就只有1200分QAQ
真的大失败
题解?
A:
由于长度只有1000,所以再反过来输出还想可以啊。。
太水了,多看了好多次题面,你说是A题也不可以这么水吧。。
B:
直接O(1000000)预处理
爱怎么搞怎么搞
太水了,多看了好多次题面,你说是B题也不可以这么水吧。。
C:
直接没有用多少个长度为a的循环节,长度为b的循环节就可以了
太水了,题面还有没说任意一组解,于是看了好多次题面,你说是C题也不可以水+描述不够吧,就是没有判-1点,WA掉了,我真是。。。。。
F:
子树问题,容易想到dus on tree
然后这种类似于插入一次函数的东西,容易想到超哥线段树
每一个点就是插入一个斜率为
b[x]
b
[
x
]
,截距为
ans[x]
a
n
s
[
x
]
的直线
对于重儿子的子树,写一个超哥线段树维护一下就可以了
时间复杂度
O(nlog2n)
O
(
n
l
o
g
2
n
)
一开始因为dsu写错WA了好多发QAQ
CODE:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MAX=(1LL<<55);
const LL N=100005;
struct qq
{
LL x,y,last;
}e[N*2];LL num,last[N];
LL n;
LL a[N],B[N];
void init (LL x,LL y)
{
num++;
e[num].x=x;e[num].y=y;
e[num].last=last[x];
last[x]=num;
}
LL ans[N];
LL tot[N],son[N];
void dfs (LL x,LL fa)
{
tot[x]=1;
for (LL u=last[x];u!=-1;u=e[u].last)
{
LL y=e[u].y;
if (y==fa) continue;
dfs(y,x);
tot[x]+=tot[y];
if (tot[y]>tot[son[x]]) son[x]=y;
}
}
LL s1[N*8],s2[N*8],k[N],b[N];//�����߶���
LL tr[N*8];
LL root;
bool Jud (LL x,LL y,LL pos)//��pos����ط���x������yҪ��
{
return b[x]+k[x]*pos<b[y]+k[y]*pos;
}
void change (LL &now,LL l,LL r,LL x)
{
if (now==0)
{
now=++num;
tr[now]=x;
s1[now]=0;s2[now]=0;
return ;
}
if (l==r)
{
if (Jud(x,tr[now],l))
tr[now]=x;
return ;
}
LL mid=(l+r)>>1;
if (k[x]<k[tr[now]])//������б�ʸ�С
{
if (Jud(x,tr[now],mid))//������ʱ�����Ѿ������ˣ���ô�ұ߾�û��
change(s1[now],l,mid,tr[now]),tr[now]=x;
else
change(s2[now],mid+1,r,x);
}
else
{
if (Jud(x,tr[now],mid))
change(s2[now],mid+1,r,tr[now]),tr[now]=x;
else change(s1[now],l,mid,x);
}
}
LL get (LL x,LL y)
{
return k[x]*y+b[x];
}
LL get_min (LL now,LL l,LL r,LL x)
{
if (now==0) return MAX;
LL mid=(l+r)>>1;
LL ans=get(tr[now],x);
// printf("%I64d %I64d %I64d %I64d %I64d %I64d %I64d\n",now,l,r,tr[now],ans,k[tr[now]],b[tr[now]]);
if (x<=mid) ans=min(ans,get_min(s1[now],l,mid,x));
else ans=min(ans,get_min(s2[now],mid+1,r,x));
return ans;
}
void Dfs (LL xx,LL x,LL fa)
{
ans[xx]=min(ans[xx],ans[x]+B[x]*a[xx]);
change(root,-100000,100000,x);
for (LL u=last[x];u!=-1;u=e[u].last)
{
LL y=e[u].y;
if (y==fa) continue;
Dfs(xx,y,x);
}
}
void solve (LL x,LL fa)
{
if (son[x]==0)//Ҷ��
{
k[x]=B[x];b[x]=0;
change(root,-100000,100000,x);
return ;
}
for (LL u=last[x];u!=-1;u=e[u].last)
{
LL y=e[u].y;
if (y==fa||y==son[x]) continue;
solve(y,x);
}
root=num=0;
solve(son[x],x);
//printf("%d\n",x);
ans[x]=get_min(root,-100000,100000,a[x]);
for (int u=last[x];u!=-1;u=e[u].last)
{
int y=e[u].y;
if (y==fa||y==son[x]) continue;
Dfs(x,y,x);
}
k[x]=B[x];b[x]=ans[x];
change(root,-100000,100000,x);
}
int main()
{
num=0;memset(last,-1,sizeof(last));
scanf("%I64d",&n);
for (LL u=1;u<=n;u++) scanf("%I64d",&a[u]);
for (LL u=1;u<=n;u++) scanf("%I64d",&B[u]);
for (LL u=1;u<n;u++)
{
LL x,y;
scanf("%I64d%I64d",&x,&y);
init(x,y);init(y,x);
}
dfs(1,0);
// for (int u=1;u<=n;u++) printf("%I64d %I64d\n",u,son[u]);
num=0;
solve(1,0);
for (LL u=1;u<=n;u++) printf("%I64d ",ans[u]);
return 0;
}