题意:在树中找到一个点i,并且找到这个点子树中的一些点组成一个集合,使得集合中的所有点的c之和不超过M,且Li*集合中元素个数和最大

首先,我们将树处理出dfs序,将子树询问转化成区间询问。

然后我们发现,对于单一节点来说,“使得集合中的所有点的c之和不超过M,且Li*集合中元素个数和最大”可以贪心地搞,即优先选择c较小的点。(<--这正是主席树/权值线段树/权值分块的工作)

但是我们需要枚举所有节点,从他们中选一个最大的。

既然有dfs序了,那么就是无修改的区间询问咯。(<--莫队的工作) 但是莫队转移的过程中,主席树/权值线段树的插入/删除无法承受。(当然主席树根本就用不着莫队,也可以解决这个问题,但这不是这篇文章要介绍的) 权值分块的插入/删除是O(1)的,查询是O(sqrt(n))的,总复杂度仍是O(n*sqrt(n))的。

编程复杂度较低,常数较小。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
ll sumv[330],m,ans;
int num2[100001],num[100001],l[330],cnts[330],b[100001],sum=1;
struct Point{int v,p;}t[100001];
struct Ask{int l,r,p;}Q[100001];
bool operator < (const Point &a,const Point &b){return a.v<b.v;}
bool operator < (const Ask &a,const Ask &b)
{return num2[a.l]!=num2[b.l] ? num2[a.l]<num2[b.l] : a.r<b.r;}
int v[100001],first[100001],next[100001];
int n,es,p,w[100001],w2[100001],L,a[100001],ma[100001],en,lead[100001];
void AddEdge(const int &U,const int &V)
{
v[++es]=V;
next[es]=first[U];
first[U]=es;
}
void dfs(int U)
{
Q[U].l=++L; t[L].v=w[U]; t[L].p=L; lead[L]=w2[U];
for(int i=first[U];i;i=next[i]) dfs(v[i]);
Q[U].r=L; Q[U].p=U;
}
void Val_Make_Block()
{
int sz=sqrt(en); if(!sz) sz=1;
for(;sum*sz<en;++sum)
{
l[sum]=(sum-1)*sz+1; int r=sum*sz;
for(int i=l[sum];i<=r;++i) num[i]=sum;
}
l[sum]=(sum-1)*sz+1;
for(int i=l[sum];i<=en;++i) num[i]=sum;
}
void Mo_Make_Block()
{
int sum=1,sz=sqrt(n); if(!sz) sz=1;
for(;sum*sz<n;++sum)
{
int r=sum*sz;
for(int i=(sum-1)*sz+1;i<=r;++i) num2[i]=sum;
}
for(int i=(sum-1)*sz+1;i<=n;++i) num2[i]=sum;
}
void Insert(const int &x){++b[x]; ++cnts[num[x]]; sumv[num[x]]+=(ll)ma[x];}
void Delete(const int &x){--b[x]; --cnts[num[x]]; sumv[num[x]]-=(ll)ma[x];}
int Query()
{
ll tot=0; int res=0;
for(int i=1;i<=sum;++i)
{
tot+=sumv[i]; res+=cnts[i];
if(tot>m)
{
tot-=sumv[i]; res-=cnts[i];
for(int j=l[i];;++j)
{
tot+=((ll)ma[j]*(ll)b[j]);
res+=b[j];
if(tot>m) return res-(int)((tot-m)/ma[j])-((tot-m)%ma[j]!=0);
}
}
}
return res;
}
int main()
{
scanf("%d%lld",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d%d%d",&p,&w[i],&w2[i]);
AddEdge(p,i);
}
dfs(1); sort(t+1,t+n+1);
ma[a[t[1].p]=++en]=t[1].v;
for(int i=2;i<=n;++i)
{
if(t[i].v!=t[i-1].v) ++en;
ma[a[t[i].p]=en]=t[i].v;
}
Val_Make_Block(); Mo_Make_Block();
sort(Q+1,Q+n+1);
for(int i=Q[1].l;i<=Q[1].r;++i) Insert(a[i]);
ans=max(ans,(ll)Query()*(ll)lead[Q[1].l]);
for(int i=2;i<=n;++i)
{
if(Q[i].l<Q[i-1].l) for(int j=Q[i-1].l-1;j>=Q[i].l;--j) Insert(a[j]);
else for(int j=Q[i-1].l;j<Q[i].l;++j) Delete(a[j]);
if(Q[i].r<Q[i-1].r) for(int j=Q[i-1].r;j>Q[i].r;--j) Delete(a[j]);
else for(int j=Q[i-1].r+1;j<=Q[i].r;++j) Insert(a[j]);
ans=max(ans,(ll)Query()*(ll)lead[Q[i].l]);
}
printf("%lld\n",ans);
return 0;
}

  

【DFS序】【莫队算法】【权值分块】bzoj2809 [Apio2012]dispatching的更多相关文章

  1. HDU 4358 Boring counting dfs序+莫队算法

    题意:N个节点的有根树,每个节点有一个weight.有Q个查询,问在以u为根的子树中,有恰好出现了K次的weight有多少种. 这是第一次写莫队算法,之前也只是偶有耳闻. 看了别人的代码打的,还是贴上 ...

  2. hdu 4358 Boring counting 离散化+dfs序+莫队算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight ...

  3. BZOJ2038: [2009国家集训队]小Z的袜子(hose) -- 莫队算法 ,,分块

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 3577  Solved: 1652[Subm ...

  4. 莫队算法 sqrt(n)分块思想

    在此说一下本渣对莫队算法思想的一些浅薄理解 莫队算法的思想就是对真个区间的分块,然后按照每块来分别进行计算,这样最终的复杂度可以达到n*sqrt(n) 小Z的袜子是一道非常经典的题目.:题目链接htt ...

  5. hdu 4358 Boring counting dfs序+莫队+离散化

    Boring counting Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others) ...

  6. CF600E Lomsat gelral (dfs序+莫队)

    题面 题解 看到网上写了很多DSU和线段树合并的题解,笔者第一次做也是用的线段树合并,但在原题赛的时候却怕线段树合并调不出来,于是就用了更好想更好调的莫队. 这里笔者就说说莫队怎么做吧. 我们可以通过 ...

  7. Codeforces 375D - Tree and Queries(dfs序+莫队)

    题目链接:http://codeforces.com/contest/351/problem/D 题目大意:n个数,col[i]对应第i个数的颜色,并给你他们之间的树形关系(以1为根),有m次询问,每 ...

  8. Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

    题目链接  Tree and Queries 题目大意  给出一棵树和每个节点的颜色.每次询问$vj, kj$ 你需要回答在以$vj$为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少 ...

  9. Luogu 1494 - 小Z的袜子 - [莫队算法模板题][分块]

    题目链接:https://www.luogu.org/problemnew/show/P1494 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天 ...

  10. 莫队或权值线段树 或主席树 p4137

    题目描述 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入格式 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l,r. 输出格式 ...

随机推荐

  1. iOS 单元测试(Unit Test 和 UI Test)

    之前一直搞过~~最近试了一下下,完美~~ 附上一篇文章,不同的伙伴可以看看: http://www.jianshu.com/p/009844a0b9edUnitTest(简单的单元测试使用) http ...

  2. maven在add dependecy时搜索不出jar包的解决办法

    一:前言 其实我一直都很头疼maven的项目管理的,因为觉得用起来还是没有那么方便的啊,不过今天我自己算是小弄了下maven项目的故那里,是一个同事在配置maven的项目,我去凑了下热闹而已,现在自己 ...

  3. nginx proxy_buffer_size 解决后端服务传输数据过多,其实是header过大的问题

    nginx proxy_buffer_size 解决后端服务传输数据过多,其实是header过大的问题 这三个参数已设置就搞定了额 proxy_buffer_size 64k; proxy_buffe ...

  4. 【Foreign】树 [prufer编码][DP]

    树 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 3 2 2 1 Sample Outp ...

  5. js中typeof 与instanceof的区别

    1.typeof 用来检测给定变量的数据类型,其返回的值是下列某个字符串: "undefined":变量未定义 "boolean":变量为布尔类型 " ...

  6. 关于集合的size的操作

    1.创建集合: 创建指定大小的集合:(大小为5) db.createCollection(}) 2.插入五条数据: > db.colle1.insert({name:}) WriteResult ...

  7. inno setup 5 添加快捷方式默认选中

    转载:https://www.cnblogs.com/x_wukong/p/5012412.html https://zhidao.baidu.com/question/312006120.html ...

  8. Linux kernel中断子系统之(五):驱动申请中断API【转】

    转自:http://www.wowotech.net/linux_kenrel/request_threaded_irq.html 一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的 ...

  9. STL各个数据结构特点

    STL容器特征总结 2011-11-09 11:10:50|  分类: STL|举报|字号 订阅     STL中顺序容器类和关联式容器类的主要特征如下:(1)Vector 1.内部数据结构:连续存储 ...

  10. python中的迭代器详解

    #原创,转载请先联系 理论性的东西有点枯燥,耐心点看- 1.迭代是什么? 我们知道可以对list,tuple,dict,str等数据类型使用for...in的循环语法,从其中依次取出数据,这个过程叫做 ...