首页 > 其他分享 >FJOI2018 领导集团问题 题解

FJOI2018 领导集团问题 题解

时间:2023-08-16 23:22:06浏览次数:52  
标签:rt le int 题解 领导 FJOI2018 gets wz ls

先考虑暴力 dp。设 \(f_{u,x}\) 表示在子树 \(u\) 中选出的节点集合的
\(w\) 最小值为 \(x\) 的情况下,最大的节点集合的大小。有两种转移(选不选 \(u\)):

\(f_{u,x}\gets \sum\limits_{v\in \text{substree}_u} f_{v,\ge x}\)

\(f_{u,w_u}\gets \sum\limits_{v\in \text{substree}_u} f_{v,\ge w_u}+1\)


考虑优化一下状态:令 \(F_{u,x}=\max\limits_{y\ge x} f_{u,y}\) 。

\(F_{u,x}\gets \sum\limits_{v\in \text{substree}_u} F_{v,x}(1\le x\le n)\)

\(F_{u,x}\gets \sum\limits_{v\in \text{substree}_u} F_{v,w_u}+1(1\le x\le w_u)\)

这样可以直接线段树合并做的,但是我理解不了这种做法。


考虑第二种转移,被被更新的 \(x\) 一定是一个后缀,因为 \(f_u\) 单调不增。

考虑差分,令 \(g_{u,x}=F_{u,x}-F_{u,x+1}\),\(L:x_{max}\ s.t\ F_{u,x}\ge F_{u,w_u}+1\)。于是转移变为:

\(g_{u,x}\gets \sum\limits_{v\in \text{substree}_u} g_{v,x}(1\le x\le n)\)

\(F_{u,x}\gets F_{u,x}+1(L\le x\le w_u)\Leftrightarrow g_{u,w_u}\gets g_{u,w_u}+1,g_{u,L-1}\gets g_{u,L-1}-1\)

考虑 \(L-1\) 在 \(g\) 中的意义,发现是 \(g_{u,[1,w_u]}\) 中最后一个不为 \(0\) 的,于是线段树上二分查找一下即可。我们分析一下操作,发现只需线段树合并,区间和,单点加,这就是板子啦!具体看代码。

#include<bits/stdc++.h>
#define LL long long
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
const int N=2e5+5;
int n,len,a[N],b[N],rt[N],tot,c[N*50],ls[N*50],rs[N*50];//50是因为2logn,肯定开大多了,我习惯 
vector<int>g[N];
void updata(int l,int r,int &wz,int p,int x)
{
	if(!wz) wz=++tot;if(l==r) return c[wz]+=x,void();
	int mid=(l+r)>>1;(p<=mid)?updata(l,mid,ls[wz],p,x):updata(mid+1,r,rs[wz],p,x);
	c[wz]=c[ls[wz]]+c[rs[wz]];
}//单点加 
int query(int l,int r,int wz,int L,int R)
{
	if(L<=l&&r<=R) return c[wz];int mid=(l+r)>>1,ans=0;
	if(L<=mid) ans+=query(l,mid,ls[wz],L,R);
	if(mid<R) ans+=query(mid+1,r,rs[wz],L,R);return ans;
}//查询区间和 
int Find(int l,int r,int wz,int k)
{
	if(l==r) return c[wz]?l:0;int mid=(l+r)>>1;
	if(c[ls[wz]]>=k) return Find(l,mid,ls[wz],k);
	return Find(mid+1,r,rs[wz],k-c[ls[wz]]);
}//查询最后一个不为0的数,如果[mid+1,w_u]这段都为0,则 c[ls[wz]]>=k,走左边(由于是最后一个优先左),否则走右边。 注意有可能全为0。 
int hb(int l,int r,int wz,int wz1)
{
	if(!wz||!wz1) return wz+wz1;
	if(l==r) return c[wz]+=c[wz1],wz;int mid=(l+r)>>1;
	ls[wz]=hb(l,mid,ls[wz],ls[wz1]),rs[wz]=hb(mid+1,r,rs[wz],rs[wz1]);
	return c[wz]=c[ls[wz]]+c[rs[wz]],wz;
}//线段树合并,基础操作 
void dfs(int x)
{
	for(int i:g[x]) dfs(i),rt[x]=hb(1,len,rt[x],rt[i]);
	int t=query(1,len,rt[x],1,a[x]),w=Find(1,len,rt[x],t);
	updata(1,len,rt[x],a[x],1);(w)&&(updata(1,len,rt[x],w,-1),1);
}//没啥好说的,注意 w 可能为 0,就是不需要 -1 啦! 
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];sort(b+1,b+1+n);len=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+len,a[i])-b;
	for(int i=1,x;i<n;i++) cin>>x,g[x].push_back(i+1);dfs(1);
	return cout<<c[rt[1]],0;
}

标签:rt,le,int,题解,领导,FJOI2018,gets,wz,ls
From: https://www.cnblogs.com/HaHeHyt/p/17636473.html

相关文章

  • [CF1730D] Prefixes and Suffixes 题解
    首先发现后缀和前缀比较不好看,所以翻转第二个字符串,记为\(T'\)。这样就变成了操作两个字符串的前缀。观察发现,操作\(k\)等价于交换\(S[1\simk]\)和\(T'[1\simk]\),然后翻转\(S[1\simk]\)和\(T'[1\simk]\)。结论1:同一个下标上的字符对恒定。因为我们所有的操作都......
  • CF932E Team Work 题解
    Description给定\(n,k\),求:\[\displaystyle\sum_{i=1}^{n}{\binom{n}{i}\timesi^k}\]\(1\leqk\leq5000,1\leqn\leq10^9\)。Solution看到那个\(i^k\)很不爽,但是\(k\)很小,考虑用斯特林数改写一下:\[i^k=\sum_{j=0}^{k}{\binom{i}{j}\left\{{\begin{matrix}k......
  • P1110题解
    首先我们考虑第一种情况怎么处理,显然我们可以给原数列的每个数开一个\(vector\),每加一个数丢到对应的\(vector\)后面就行了。再看第二个操作,你考虑新加一个数会有什么影响。原来的两个\(vector\)是这样的:新加一个数进去以后:原来的\(|y-x|\)要删除,新增了\(|x-z|\)和\(|z-y|\)......
  • 【题解】[ARC158C] All Pair Digit Sums
    传送门题目分析我们可以先从简单一点的情况开始分析,如果现在\(a_{[i]},a_{[j]}\)都不会进位,那么最后的\(f(a_{[i]}+a_{[j]})=f(a_{[i]})+f(a_{[j]})\)。证明如下:有两个数\(x=\overline{x_nx_{n-1}....x_1}\)和\(y=\overline{y_my_{m-1}...y_1}\)。令\(n\lem\),由于不会......
  • vscode git突然失效问题解决
    一:首先配置‘环境变量’打开电脑‘设置’----->关于--->高级系统设置---->环境变量------>用户和系统变量都设置一下,点击Path------->新建-------->将git-bash的应用程序地址粘贴到里面----->一直点击确定,直到退出(这里的应用程序地址看自己保存的bash.exe的位置)我的是:C:\Program......
  • 新生赛题解
    A题解:不会#include<bits/stdc++.h>#pragmaGCCoptimize("Ofast")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<cmath>//#definedoublelongdoub......
  • P2073题解
    链接:P2073送花题意:有若干朵花,每个有两个属性(美丽值和价格)。你需要维护\(3\)种操作:1.添加一朵花(如果之前有价格相同的忽略此操作)2.删除最贵的花3.删除最便宜的花最后输出两个数:美丽值的总和和价格总和解法:经典的平衡树题。对于第一种操作,关键在于判重。先询问一下有......
  • 安防视频监控平台EasyNVR视频监控汇聚平台页面无法上传授权文件的问题解决方案
    TSINGSEE青犀视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入,并能对接入的视频流进行处理与多端分发,包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。在智慧安防等视频监控场景中,EasyNVR可提供视频实时监控直播、云端录像、云存储、录像检索与回看、告警等......
  • CF809E 题解
    一棵树,点权\(a_i(a_i\len)\),无边权,求\[\sum_{i\nej}\varphi(a_ia_j)\text{dis}(i,j)\]首先,你没有任何手段求\(10^{10}\)级别的一堆离散的\(\varphi\)。于是\[\varphi(xy)=\frac{\varphi(x)\varphi(y)\gcd(x,y)}{\varphi(\gcd(x,y))}\]然后一通莫反,枚举\(\gcd\)\[\sum......
  • CF1648E 题解
    就是\(m\)组询问补图的最小生成树上的树链最大值。有两种基本思路求这棵树。第一种,Kruskal,基于找到最小的边使两端点不连通。考虑补图中\((x,y)\)的边权,它是原图最小生成树上的树链最大值。从小到大枚举补图的边,相当于从小到大枚举原图最小生成树的边\((u,v,w)\),然后:令原图......