题面



65

看到路径问题,就想到了套路:点分治。

对于一个分治中心,先把在其子树的结点的sum和mn求出来,分别表示该节点到分治中心的边权和和点权最小值。

然后把mn离散化,并插入权值线段树中,以sum为关键字。

为了解决最小值的问题,我们需要使得最小值在某棵子树中,然后枚举其他子树中mn值比他大的结点的贡献。

首先我想到的就是一棵一棵子树的增量法,但是因为每棵子树一进一出,所以在菊花图中的复杂度到达平方。

然后我就想到了先把这棵树先加进去,枚举一棵子树,然后再撤销掉线段树中的这棵子树。

枚举分治中心的每棵子树,强制使最小值在其中。

那么对于这棵子树内的任一结点\(v\)的贡献为$$ans=mn[v]*(sum[v]+query(1,n,1,rk[v],n))$$

这样的复杂度是\(O(nlog^2n)\)的,谈不上优秀,所以被出题人硬是卡掉了。


然后我还想吐槽一下的是,berber的\(O(n^2logn)\)点分过了。

他用的是增量法。

100

满分做法也是相当套路。

为了解决掉最小值的问题。

我们把点权从大到小排序,逐个插入。

每次插入后,求一下森林的直径。

由于直径可以合并,所以时间复杂度是\(O(nlogn)\)的。

Code(65)

#include<bits/stdc++.h>
#define ll long long
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const char* fin="2.in";
const char* fout="2.out";
const int inf=0x7fffffff;
int read(){
int x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
const int maxn=100007,maxm=maxn*2;
struct node{int x,y;}w[maxn];
bool cmp(node a,node b){return a.x<b.x;}
int n,N,a[maxn],rk[maxn]={0},Rk[maxn],fi[maxn],la[maxm],ne[maxm],va[maxm],tot,rt;
ll ans;
void add_line(int a,int b,int c){
tot++;
ne[tot]=fi[a];
la[tot]=b;
va[tot]=c;
fi[a]=tot;
}
bool bz[maxn];
int b[maxn][2],hd,tl,si[maxn];
void getsi(int v){
hd=0;
b[tl=1][0]=v;
b[tl][1]=0;
while (hd++<tl){
int v=b[hd][0],from=b[hd][1];
si[v]=1;
for(int k=fi[v];k;k=ne[k])
if (!bz[la[k]] && la[k]!=from){
b[++tl][0]=la[k];
b[tl][1]=v;
}
}
fd(i,tl,1){
int v=b[i][0],from=b[i][1];
for(int k=fi[v];k;k=ne[k]) if (!bz[la[k]] && la[k]!=from) si[v]+=si[la[k]];
}
}
void getrt(int x){
getsi(x);
if (si[x]==1) rt=x;
else fo(i,1,tl){
int v=b[i][0],from=b[i][1];
bool nort=false;
for(int k=fi[v];k;k=ne[k])
if (la[k]!=from && !bz[la[k]]) nort|=(si[la[k]]>si[x]/2);
if (!nort && si[x]-si[v]<=si[x]/2) rt=v;
}
}
ll sum[maxn],c[maxn*4];
int mn[maxn];
int B[maxn][2],head,tail;
void modify(int l,int r,int t,int v,ll ad){
int mid=(l+r)/2;
if (l==r){c[t]=ad;return;}
if (v<=mid) modify(l,mid,t*2,v,ad);
else modify(mid+1,r,t*2+1,v,ad);
c[t]=max(c[t*2],c[t*2+1]);
}
ll query(int l,int r,int t,int v1,int v2){
int mid=(l+r)/2;
if (l>v2 || r<v1) return 0;
if (l>=v1 && r<=v2) return c[t];
return max(query(l,mid,t*2,v1,v2),query(mid+1,r,t*2+1,v1,v2));
}
void work(int x){
head=0;
B[tail=1][0]=x;
B[tail][1]=0;
while (head++<tail){
int v=B[head][0],from=B[head][1];
modify(1,N,1,Rk[v],0);
for(int k=fi[v];k;k=ne[k])
if (!bz[la[k]] && la[k]!=from){
B[++tail][0]=la[k];
B[tail][1]=v;
}
}
fo(i,1,tail){
int v=B[i][0];
ans=max(ans,mn[v]*(query(1,N,1,rk[v],N)+sum[v]));
}
fo(i,1,tail) modify(1,N,1,Rk[B[i][0]],sum[B[i][0]]);
}
void solve(int x){
hd=N=0;
sum[x]=0,mn[x]=a[x];
b[tl=1][0]=x;
b[tl][1]=0;
while (hd++<tl){
int v=b[hd][0],from=b[hd][1];
w[++N].x=mn[v],w[N].y=v;
for(int k=fi[v];k;k=ne[k])
if (!bz[la[k]] && la[k]!=from){
b[++tl][0]=la[k];
b[tl][1]=v;
mn[la[k]]=min(mn[v],a[la[k]]);
sum[la[k]]=sum[v]+va[k];
}
}
sort(w+1,w+N+1,cmp);
fo(i,1,N){
if (i==1 || w[i].x!=w[i-1].x) rk[w[i].y]=i;
else rk[w[i].y]=rk[w[i-1].y];
Rk[w[i].y]=i;
}
fo(i,1,tl) modify(1,N,1,Rk[b[i][0]],sum[b[i][0]]);
for(int k=fi[x];k;k=ne[k]) if (!bz[la[k]]) work(la[k]);
fo(i,1,tl) modify(1,N,1,Rk[b[i][0]],0);
}
void dfs(int v){
bz[v]=true;
solve(v);
for(int k=fi[v];k;k=ne[k])
if (!bz[la[k]]){
getrt(la[k]);
dfs(rt);
}
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
int t=read();
while (t--){
n=read();
memset(fi,0,sizeof fi);
memset(bz,0,sizeof bz);
tot=0;
fo(i,1,n) a[i]=read();
fo(i,1,n-1){
int j=read(),k=read(),l=read();
add_line(j,k,l);
add_line(k,j,l);
}
ans=0;
getrt(1);
dfs(rt);
printf("%lld\n",ans);
}
return 0;
}

……

表示打这道题打得很爽快。

比赛的时候把很多时间都投入到了这一题。

比较不幸的是出题人卡了log方做法。

这就导致我比赛总分65,其他题都来不及打。

本来第3题可以100,被lhy骚扰一下,小于号改成了大于号,一个字符之差,丢了100分。

【JZOJ5338】【NOIP2017提高A组模拟8.25】影子 点分治?/ 排序的更多相关文章

  1. JZOJ 100029. 【NOIP2017提高A组模拟7.8】陪审团

    100029. [NOIP2017提高A组模拟7.8]陪审团 Time Limits: 1000 ms  Memory Limits: 131072 KB  Detailed Limits   Got ...

  2. JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线

    5328. [NOIP2017提高A组模拟8.22]世界线 (File IO): input:worldline.in output:worldline.out Time Limits: 1500 m ...

  3. JZOJ 5329. 【NOIP2017提高A组模拟8.22】时间机器

    5329. [NOIP2017提高A组模拟8.22]时间机器 (File IO): input:machine.in output:machine.out Time Limits: 2000 ms M ...

  4. JZOJ 5307. 【NOIP2017提高A组模拟8.18】偷窃 (Standard IO)

    5307. [NOIP2017提高A组模拟8.18]偷窃 (Standard IO) Time Limits: 1000 ms Memory Limits: 262144 KB Description ...

  5. JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林 (Standard IO)

    5286. [NOIP2017提高A组模拟8.16]花花的森林 (Standard IO) Time Limits: 1000 ms Memory Limits: 131072 KB Descript ...

  6. JZOJ 5305. 【NOIP2017提高A组模拟8.18】C (Standard IO)

    5305. [NOIP2017提高A组模拟8.18]C (Standard IO) Time Limits: 1000 ms Memory Limits: 131072 KB Description ...

  7. 【NOIP2017提高A组模拟9.17】信仰是为了虚无之人

    [NOIP2017提高A组模拟9.17]信仰是为了虚无之人 Description Input Output Sample Input 3 3 0 1 1 7 1 1 6 1 3 2 Sample O ...

  8. 【NOIP2017提高A组模拟9.17】猫

    [NOIP2017提高A组模拟9.17]猫 题目 Description 信息组最近猫成灾了! 隔壁物理组也拿猫没办法. 信息组组长只好去请神刀手来帮他们消灭猫.信息组现在共有n 只猫(n 为正整数) ...

  9. 【NOIP2017提高A组模拟9.17】组合数问题

    [NOIP2017提高A组模拟9.17]组合数问题 题目 Description 定义"组合数"S(n,m)代表将n 个不同的元素拆分成m 个非空集合的方案数. 举个例子,将{1,2,3}拆分成2 个 ...

随机推荐

  1. 安卓手机端微信网页浏览记录清理debugx5.qq.com

    最近我们环境从复)星(云切换到阿里云.早上地铁路上就有小伙伴@,一阵搜索.找的如下的方法. 记录一下: 目前只支持安卓手机的微信内置浏览器清理. 由腾讯提供的网址http://debugx5.qq.c ...

  2. 47 Majority Element II

    原题网址; https://www.lintcode.com/problem/majority-element-ii/ 描述 给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的三 ...

  3. jeecms v9库内新增对象的流程及其他技巧

    cms 开发 ———— 库内新增对象 Products 的流程说明及其他技巧 第一步:Entity com.jeecms.cms.entity.assist.base下建立模型基础类BaseCmsPr ...

  4. elasticsearch配置优化

    调整ES内存分配有多种方式,建议调整 elasticsearch 中的设置(还可以直接修改bin下的启动脚本). # Directory where the Elasticsearch binary ...

  5. java编程题古典算法之兔子问题

    1.题目如下. 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析每个月的兔子对数: 1---- ...

  6. Python实例1-Collatz 序列

    编写一个名为 collatz()的函数,它有一个名为 number 的参数.如果参数是偶数,那么 collatz()就打印出 number // 2, 并返回该值.如果 number 是奇数, col ...

  7. python 之 heapq (堆)

    堆的实现通过构造二叉堆,实为二叉树的一种:这种数据结构具有以下性质: 任意节点小于(或大于)它的后裔,最小元(或最大元)在堆的根上 堆总是一颗完整树.即除了最低层,其它层的节点都被元素填满,且最低层极 ...

  8. 如何做系列(2)- XML转义字符

    < < 小于号 > > 大于号 & & 和 &apos; ' 单引号 " " 双引号 也可以使用<![CDATA[ ]]> ...

  9. goland破解

    PyCharm是由著名的JetBrains公司所打造的一款功能强大的Python IDE,它具有一般IDE都具备的功能,并且使用起来非常方便好用.最近需求PyCharm激活码的网友非常多,小编就在这里 ...

  10. 快速傅里叶变换(FFT)学习

    首先,在写这篇博客之前,我还没有完全学会FFT. 先把会的部分打好,加深一下记忆(也可以说是做笔记吧). 初三了,还不会FFT,要退役喽-- 多项式乘法 点开这篇博客之前,你就应该知道,FFT是用来求 ...