https://zybuluo.com/ysner/note/1240918

题面

这题面不好概括啊

解析

\(5pts\)算法

既然\(q=0\),打上文件输入输出即可。

当然不开够空间且不特判的小朋友就拿不到了。

\(15pts\)算法

\(n\leq10,q\leq10\)。

所有人在\(lca\)聚会是显然的吧(毕竟每个人只能往上走)。

这怎么乱搞都可以。

可以\(O(m^c)\)枚举每个特产被哪个人带,再检查一下是否可行和合法(每个人带的特产数相同)即可。

复杂度似乎是\(O(m^cclogn)\)???

\(32pts\)算法

\(c\leq2\),两个人讨论起来比较方便。

先统计出三个信息\(s_1,s_2,s_3\),\(s_1\)表示两个人都可取到的特产数,\(s_2\)表示第一个人可取到的,\(s_3\)表示第二个人可取到的。

显然,若\(s_1+s_2<s_3\),则\(ans=s_1+s_2\)

若\(s_1+s_3<s_2\),则\(ans=s_1+s_3\)

若以上均不满足,则\(ans=(s_1+s_2+s_3)/2\)

复杂度\(O(qclogn)\)

\(45pts\)算法

\(c\leq3\),估计出题人想让我们维护\(6\)个信息再讨论。。。

如果你能写出来,你会发现复杂度同上。

\(65pts\)算法

匹配问题是可以用网络流来解的。

我们可以统计一下每个特产能被哪些人选。

然后???

\(100pts\)算法

我考场上一直不会维护链上颜色个数,以为需要树上莫队。。。

实际上,因为颜色数只有\(1000\),开个\(bitset\)并没有什么问题。

于是可以树链剖分+线段树+\(bitset\)强行\(O(nlog^2n)\)预处理每个人能选到的特产\(dp\)。

或者说可以预处理出每条链上\(bitset\)前缀和(用重儿子),这样就只用在\(top[u]=top[lca]\)这一段用线段树查询,复杂度降到\(O(nlogn)\)。

然后我们来考虑怎么来求最大的特产数。

注意到每一个人选择的特产的种数是相同的,若每一个人选\(x\)种特产,则\(ans=cx\)。

(神思路时间)

这相当于每一个人都拆成了\(x\)个点,然后人和特产之间连边跑完美二分图匹配。

怎么保证完美???

根据霍尔定理,左边的任何一个子集都要满足和右边的相邻的点数大于等于子集大小

右边相邻的点数就是当前状态中包括的人总共能取到的特产数,所以答案很明显就是\(min\{\frac{dp[now]}{|now|}\)}了。

\(now\)指当前状态包含的人数。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<bitset>
#define re register
#define il inline
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int mod=1e9+7,N=5e5+100;
struct Edge{int to,nxt;}e[N<<1];
int n,m,Q,a[N],f[N],d[N],top[N],sz[N],c,son[N],ans,h[N],cnt,q[N],id[N],now[N],tim;
il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;}
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
bitset<1010>dp[50];
bitset<1010>pre[N];
namespace seg_T
{
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((l+r)>>1)
bitset<1010>w[N<<2];
il void Build(re int x,re int l,re int r)
{
if(l==r) {w[x][a[q[l]]]=1;return;}
Build(ls,l,mid);Build(rs,mid+1,r);
w[x]=w[ls]|w[rs];
}
il void Query(re int x,re int l,re int r,re int ql,re int qr,bitset<1010>* res)
{
if(ql<=l&&r<=qr) {*res|=w[x];return;}
if(ql<=mid) Query(ls,l,mid,ql,qr,res);
if(qr>mid) Query(rs,mid+1,r,ql,qr,res);
}
}
il void dfs1(re int u,re int fa)
{
f[u]=fa;d[u]=d[fa]+1;sz[u]=1;pre[u][a[u]]=1;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==fa) continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
il void dfs2(re int u,re int up)
{
q[id[u]=++tim]=u;
top[u]=up;
if(son[u])
{
pre[son[u]]|=pre[u];
dfs2(son[u],up);
}
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==f[u]||v==son[u]) continue;
dfs2(v,v);
}
}
il int LCA(re int u,re int v)
{
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]]) swap(u,v);
u=f[top[u]];
}
return d[u]<d[v]?u:v;
}
il void calc(bitset<1010>* res,re int u,re int v)
{
while(top[u]^top[v])
{
*res|=pre[u];
u=f[top[u]];
}
seg_T::Query(1,1,n,id[v],id[u],res);
}
int main()
{
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
memset(h,-1,sizeof(h));
n=gi();m=gi();Q=gi();
fp(i,2,n)
{
re int u=i,v=gi();
add(v,u);
}
fp(i,1,n) a[i]=gi();
dfs1(1,0);dfs2(1,1);
seg_T::Build(1,1,n);
while(Q--)
{
c=gi();
fp(i,0,c-1) now[i]=gi();
re int lca=now[0];
fp(i,1,c-1) lca=LCA(lca,now[i]);
fp(i,0,c-1)
{
dp[(1<<i)].reset();
calc(&dp[(1<<i)],now[i],lca);
}
ans=m/c;
fp(i,1,(1<<c)-1)
{
re int x=i,t=0;
while(x) {x-=x&-x;++t;}
if(t^1)
{
re int tt=(i-1)&i;
dp[i]=dp[tt]|dp[i^tt];
}
ans=min(ans,(int)dp[i].count()/t);
}
printf("%d\n",ans*c);
}
fclose(stdin);
fclose(stdout);
return 0;
}

[bzoj5404]party的更多相关文章

随机推荐

  1. 梦想CAD控件事件COM接口知识点

    一.鼠标事件 _DMxDrawXEvents::MouseEvent 控件中的鼠标事件. 参数 说明 LONG lType 事件类型,1鼠标移动,2是鼠标左键按下,3是鼠标右键按下,4是鼠标左键双击 ...

  2. 牛客多校Round 5

    Solved:3 rank:195 F. take 官方题解:小 A 在打开第 i 个箱子后会交换手中的钻石和第 i 个箱子中的钻石 当且仅当第 i个箱子的钻石是前 i 个箱子打开后出现的所有钻石里最 ...

  3. Daydreaming Stockbroker(2016 NCPC 贪心)

    题目: Gina Reed, the famous stockbroker, is having a slow day at work, and between rounds of solitaire ...

  4. 总结在Linux终端中进行算术运算的6种方式

    1.使用bash 使用双括号可以像C语言一样直接使用运算符进行计算. +)) a=$((*)) echo $a b=$(($a-)) echo $b d=$(($b/)) echo $d e=$(($ ...

  5. CCF201509-2 日期计算 java(100分)

    试题编号: 201509-2 试题名称: 日期计算 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给定一个年份y和一个整数d,问这一年的第d天是几月几日? 注意闰年的2月有2 ...

  6. BZOJ 5028 小Z的加油店

    [题解] 本题要求求出区间内的各个元素通过加减之后能够得出的最小的数,那么根据裴蜀定理可知答案就是区间内各个元素的最大公约数. 那么本题题意化简成了维护一个序列,支持区间加上某个数以及查询区间元素的最 ...

  7. PAT 1129 Recommendation System

    Recommendation system predicts the preference that a user would give to an item. Now you are asked t ...

  8. 【Codeforces 484A】Bits

    [链接] 我是链接,点我呀:) [题意] 让你求出l~r当中二进制表示1的个数最多的数x [题解] 最多有64位 我们可以从l开始一直增大到r 怎么增大? 找到l的二进制表示当中0所在的位置 假设i这 ...

  9. [luoguP3047] [USACO12FEB]附近的牛Nearby Cows(DP)

    传送门 dp[i][j][0] 表示点 i 在以 i 为根的子树中范围为 j 的解 dp[i][j][1] 表示点 i 在除去 以 i 为根的子树中范围为 j 的解 状态转移就很好写了 ——代码 #i ...

  10. python函数基础:嵌套函数、作用域、匿名函数、高阶函数、递归函数

    嵌套函数: 1. 函数内部可以再定义函数 2. 函数只有被调用之后才会执行 看如下代码: age = 18 def func1(): age = 22 print(age) def func2(): ...