19CSP-S十一集训三地联考—众神归位 题解总结

订正了三天的题目 自闭....

T1 幸福T2 树链剖分

考虑到 对于一个 树 确定覆盖哪几条边 不会随着 树的根节点的改变而改变

而且 这种对于一个无根树的路径进行覆盖 我们显然可以想到 树上差分 对于边的差分

对于一条路径从s到t 我们类比序列上的差分 即 $sum[s]--,sum[t]--,sum[lca(s,t)]-=2$

所以进行一遍dfs 求出一个节点的子树权值和 就是从这个点的父节点 到这个点 被覆盖了多少次

所以我们 求出所有的和就是整棵树所有边被覆盖的次数 记作res 然后单独考虑 这个树链剖分集合的大小

首先$size[i]$ 表示 i的子树和 那么就是$fa[i]$指向$i$那条边被覆盖的次数

$maxx[i]$ 表示从i出发的边中所有的儿子y 对应的最大的$size[y]$

$maxp[i]$ 表示从i出发的边中所有的儿子y 对应的次大的$size[y]$  换根的时候会用到

然后考虑 对于一个节点来说 我们可以贪心的去选取 下一个 树链剖分的边 是指向哪个儿子的 显然是 当前被覆盖的边数次数最多的那一条边

这个贪心的正确性应该是显然的 所以我们考虑 指定不同的根节点 一定会造成不同的情况 这其中一定存在一个换根dp

我们按照刚才贪心的思路 我们可以求出来 以当前为根的子树内最大树链剖分的大小 指定1为根节点 显然存在$g[1]=所有节点的maxx[i]$

假设当前存在一条从x指向y的边 而且 $g[x]$ 已经求出 我们现在考虑 怎么求出来$g[y]$

存在状态转移方程:

$$g[y]=g[x]-max(size[x],maxx[x])-maxx[y];$$

$$g[y]+=max(size[y],maxx[y])+max(size[x],size[y]==maxx[x]?maxp[x]:maxx[x]);$$

对于第二个方程 是因为 我们需要知道x有没有选择指向y的那条边 如果选择的是y 那么 我们就要加上x出发的次大值 否则

我们就要加上最大值 此时y成为了整颗子树的根 而对于他的儿子他只能选择一条边 我们按照贪心的思路就找都这条边

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x) {
    x=0;T f=1,ch=getchar();
    while(!isdigit(ch))     {if(ch==‘-‘) f=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x*=f;
}
typedef long long ll;
const int N=100010;
ll n,m,tot,x,y,size[N],sum[N],d[N],f[N][25],lin[N];
ll g[N];//f1[i]表示以i为根的子树内的最大树链剖分
//g[i] 表示以i为整颗子树的根的最大树链剖分
ll res,maxx[N],maxp[N],sx[N],sxp[N];
struct gg {
    int y,next;
}a[N<<1];
inline void add(ll x,ll y) {
    a[++tot].y=y;
    a[tot].next=lin[x];
    lin[x]=tot;
}
inline void bfs() {
    queue<ll>q;
    q.push(1);d[1]=1;
    while(q.size()) {
        ll x=q.front(); q.pop();
        for(ll i=lin[x];i;i=a[i].next) {
            ll y=a[i].y;
            if(d[y]) continue;
            d[y]=d[x]+1;
            f[y][0]=x;
            for(int j=1;j<=23;j++)
                f[y][j]=f[f[y][j-1]][j-1];
            q.push(y);
        }
    }
}
inline ll lca(ll x,ll y) {
    if(d[x]>d[y]) swap(x,y);
    for(ll i=23;i>=0;--i) {
        if(d[f[y][i]]>=d[x])
            y=f[y][i];
    }
    if(x==y) return x;
    for(ll i=23;i>=0;--i) {
        if(f[y][i]!=f[x][i]) {
            y=f[y][i],x=f[x][i];
        }
    }
    return f[x][0];
}
inline void dfs(ll x,ll fa) {
    size[x]=sum[x];
    for(ll i=lin[x];i;i=a[i].next) {
        ll y=a[i].y;
        if(y==fa) continue;
        dfs(y,x);
        size[x]+=size[y];
        if(maxx[x]<size[y]) {
            maxp[x]=maxx[x];
            maxx[x]=size[y];
        }
        else if(size[y]>maxp[x]) {
            maxp[x]=size[y];
        }
    }
    g[1]+=maxx[x];res+=size[x];
}
inline void dp(ll x,ll fa) {
    for(ll i=lin[x];i;i=a[i].next) {
        ll y=a[i].y;
        if(y==fa) continue;
        g[y]=g[x]-max(size[x],maxx[x])-maxx[y];
        g[y]+=max(size[y],maxx[y])+max(size[x],size[y]==maxx[x]?maxp[x]:maxx[x]);
        dp(y,x);
    }
}
int main() {
    //freopen("1.in.cpp","r",stdin);
    read(n); read(m);
    for(ll i=1;i<n;i++) {
        read(x); read(y);
        add(x,y); add(y,x);
    }
    bfs();
    for(ll i=1;i<=m;i++) {
        read(x); read(y);
        sum[x]++,sum[y]++;
        ll c=lca(x,y);
        sum[c]-=2;
    }
    dfs(1,0);
    dp(1,0);
    ll ans=0,x;
    for(ll i=1;i<=n;i++)  {
        if(ans<g[i]) {
            //x=i;
            ans=g[i];
        }
    }
    cout<<res-ans<<endl;
    return 0;
}

T3

比较自闭的是 我以为分给小Ex张 而将剩下y张都给了小y

算了 这不重要 我们存在一种暴力的做法 就是枚举出来当前小E 手中每种i花色牌的数量 然后考虑对于他拥有的第i个花色的牌的数量bi

但是这样的情况过多 所以我们不妨枚举胜率 还是对于第i种花色 考虑此时小E手中拥有bi 然后考虑 此时小E选择 i花色 能赢的概率

那么此时 设小F拥有的 i 花色的牌的数量是 j 那么存在 可以使小E 获胜的方案数

设m=$\sum_{i=1}^{n} a_i$;

$\sum_{j=0}^{min(y,b_i-a_i,b_i-z)}\binom{a_i-b_i}{j}\binom{m-x-a_i+b_i}{y-j}$

解释一下上面那个式子的意义 因为当前枚举的是j 所以前半部分的 表示小F拥有j张i花色牌的方案数

而后半部分表示 小F不拿到i花色牌的数量 观察 $m-x-(a_i-b_j)$ 其实保证我们此时在备选集合内 不再拥有i花色的牌

因为当前我们要保证他能选择i花色的牌的数量是j  所以利用乘法原理 用选到i花色 乘 选到非i 花色的 数量

这里我们考虑的都是胜率的分子 因为分母是永远不变的 所以 根据上面的胜率 我们可以考虑 由最开始 枚举的小E手中的牌

改为 枚举胜率 上面那个式子的分母 显然是 $\binom{m-x}{y}$  根据分子必定小于分母 所以我们这个式子是 小于$\binom{100}{50}$ 的

根据数据范围可以知道 所以这样的答案我们可以使用__int128 存储下 而不用写高精度

考虑 我们已经求出来所有的胜率 我们还要做一个事情 我们要保证选择了bi 张i花色的牌 和x-bi张其他花色的牌

此时选择 i花色 其他花色的胜率都小于等于 i 花色这里我们考虑 dp

设$dp(i,j)$ 表示对于前i种花色 总共选出来了j张 并且每种花色的胜率都小于等于 i 花色的胜率得方案数

那么 目标状态就是 $dp(n,m-b_i)$ 考虑 此时呈上 $\binom{a_i}{b_i}$ 就是此时的贡献

显然这个题目最难想到的就是容斥 而且对于容斥的处理也比较巧妙

首先考虑为什么要容斥

根据上面 我们已经求出来了所有的胜率 假设所有的胜率两两不同

那么对于这种花色i满足限制 $b_i$ 的情况 不会存在一种j st j的胜率比 i 大 显然 这是我们在刚才dp的过程中就处理出来了

所有现在出现了一个问题 如果存在

原文地址:https://www.cnblogs.com/Tyouchie/p/11619271.html

时间: 2024-07-31 14:32:14

19CSP-S十一集训三地联考—众神归位 题解总结的相关文章

19CSP-S十一集训三地联考—众神归位

T2 树链剖分 (http://zhengruioi.com/problem/1120) gu~gu~gu~ sol: 这题就是一个很经典的树形DP换根.考虑因为是树链剖分,所以不同深度的节点是互不影响的.那DP就只要考虑当前节点连出的边中,被覆盖次数最多的即可. 主要是复习一下换根法.首先做出以\(1\)为根的情况,处理出边被覆盖次数最多和次多的情\(son1[x]\)和\(son2[x]\).考虑选择的根深度逐渐变大,每次只要修改一下答案,然后更新\(son1[x]\)和\(son2[x]\

「CSPS 2019 十一」三地联考

因为版权原因,不放题面. 幸福 Solution 只会写 \(70\) 分的找规律代码,可以考虑每个斐波那契数对卷积的贡献,发现贡献是类似于倒斐波那契数列,就可以 \(O(n)\) 做了,有 \(70\) 分. std 是化简一下式子,化简结果为 \[F_n = F_{n-1} + F_{n-2} + f_n\] 发现这是一个递推式,用矩阵乘法加速即可.但是我不会矩阵乘法,先咕了.不会矩阵乘法也可以用退出来的递推式拿 \(70\) 分. Code #include <bits/stdc++.h>

ZROI1119 【十一&#183;联考】幸福

ZROI1119 [十一·联考]幸福 传送门 一道矩阵快速幂. #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define ll long long #include<cmath> const int mod=998244353; using namespace std; struct matrix { ll data[7][7]; void

8.9联考题解

今天的题有质量多了,尤其是第一题不再毫无意义,果然考这样的试比较有收获. 时间限制:1sec  内存限制:128MB 题解       刚开始看的时候没有思路.不过这样的考试才叫正常嘛,前两天T1那是什么玩意= =.边读题边写前缀和.离散之类的词,但是前缀和并不能处理出题目中所要求的情况,3*10^5大概最多nlogn.举了几个例子,发现好像和后面大于它的数有关,想了想怎么求它后面大于它的数字个数,过了一会猛然发现我举的例子也太特殊了,全都是单调递增的,有点挫败,就去做后面的题了.T2做了很久还

jloi2017(shoi2017?)六省联考酱油记

Day -n 听说了4.22.4.23的省选,而且还是六省联考. 压力山大. 尽管我只是一名高一的simple OIer,在省选到来之前,心里还是很紧张的. 毕竟自己也知道南方dalao们都是神犇,像我这种巨蒻能考成什么样还很不好说. 感觉当时的紧张气氛堪比中考前. Teacher:这次省选就是让你们体验一下考试氛围的,并没有指望你们有多好的成绩,自己写好暴力就行了,不必非要写正解. 嗯,我本来就是去打酱油的,不在乎成绩. 考试前几天敲敲模板,博客也不写了,全力准备考试. Day 0 考前的晚上

3.5~3.6联考题解

本来想加个密码的,后来一想全HE就咱们这几个人,外省的dalao愿看也没事儿,就公开算了,省得加密码各种麻烦. 先补这两天的题解吧--如果有空的话我可能会把上次联考的题解补上= =(中午没睡觉,现在困得很,根本没法写题-- 算算算number 感觉出题人出题的时候zz了吧,费了半天搞出来一个极其麻烦还跑得慢的做法是要闹哪样啊-- 算了,写一写$O(nk)$做法的推导过程吧,虽然其实非常好推-- 首先定义$S_i$表示到$1~i$位置的前缀和,并且规定$S_0=0$,那么 \begin{align

10.29 FJ四校联考

//四校联考Rank 16 感觉很滋磁 (虽然考的时候抱怨厦门一中出的数学题很NOIP///) 圈地 [问题描述] n根长度不一定相同的木棍,至多可以对其中一根切一刀,然后用其中的任意根围一个三角形,求三角形的最大面积.设面积为S,输出16*S^2对998244353取模后的答案.特别地,无解输出-1. 注:退化的三角形(面积为零)不被认为是三角形,答案应该为-1. [输入文件] 输入文件为tri.in. 输入文件第一行包含两个正整数n和998244353. 第二行包含n个正整数,表示每根木棍的

因第三次月考而引起的

这么久没有考试了,一连翘掉了期末.入学.第一次月考.期中考试.本来这一次的第三次月考是要求全组参加的,但是,俗话说:“计划赶不上变化”.确实如此,在明天就要第三次月考的晚自习前,我们还在搞大扫除,忽然,远远望见教练的身影,他过来说:“联赛400分以上的不要参加月考,从明天开始准备冬令营.”我们这些人(4个)真是一脸茫然的样子.马上又去找了教练,他说年级组要求我们参加月考因我们不能参加冬令营.不过教练还是说会去和年级组谈一谈. 不知怎么办的我们遭遇了这当头的一棒,马上,准备去找年级组长,我们的理由

bzoj千题计划265:bzoj4873: [六省联考2017]寿司餐厅

http://www.lydsy.com/JudgeOnline/problem.php?id=4873 选a必选b,a依赖于b 最大权闭合子图模型 构图: 1.源点 向 正美味度区间 连 流量为 美味度 的边 2.负美味度区间 向 汇点 连 流量为 美味度的绝对值 的边 3.区间[i,j] 向 区间[i+1,j].区间[i,j-1] 连 流量为 inf 的边 4.区间[i,i] 向 寿司i 连 流量为 inf 的边 5.寿司i 向 汇点 连 流量为 寿司代号 的边 6.寿司i 向 它的代号 连