省选模拟13 题解

A. 同桌的你

每个人渴望与一个人当同桌。

容易发现这个关系形成内向基环树森林。

问题转化为求基环树森林的最大匹配。

任意选一条环上的边,分别尝试该边为匹配边、非匹配边即可。

B. 大水题

一个常用的但想不到的东西:将每种颜色出现次数的差值为定值,转化为对颜色序列差分后相等。

然后暴力的做法是枚举2^8,表示答案出现在指定的颜色集合中,分别将差分数组插入、查询哈希表即可。

下面是一个优化:

容易发现可行的颜色集合对于同一个时刻只有不超过8种。

对于每一个左端点,随着右端点的右移,区间颜色集合改变次数不超过8次。

当右端点右移时,给区间颜色集合需要改变的,添加新的一种颜色。

具体实现方式是维护一个$lst$数组,表示第$i$种颜色的最后一次出现位置。

可以参考代码。

 1 #include<bits/stdc++.h>
 2 #define ull unsigned long long
 3 using namespace std;
 4 const int N=1e5+7;
 5 int n,k;
 6 pair<int,int> f[N],t[10];
 7 struct Hash{
 8     const static int p=2333333;
 9     int tot,head[p],nxt[p],val[p];
10     ull to[p];
11     inline int& operator [](ull x){
12         int y=x%p;
13         for(int i=head[y];i;i=nxt[i]) if(to[i]==x) return val[i];
14         nxt[++tot]=head[y]; to[head[y]=tot]=x;
15         return val[tot]=-1;
16     }
17 }mp;
18 int lst[10],cnt[10][N];
19 ull pw[10];
20 inline int calc(int s,int t){
21     int r=0;
22     for(int i=1;i<=8;++i) if(cnt[i][t]-cnt[i][s]) r|=1<<i-1;
23     return r;
24 }
25 inline ull solve(int x,int s){
26     ull r=0; int fir=8;
27     for(int i=1;i<=8;++i) if(s>>i-1&1){ fir=i; break; }
28     for(int i=fir+1;i<=8;++i) if(s>>i-1&1) r=r*133331+cnt[i][x]-cnt[fir][x];
29     return r+s*pw[8];
30 }
31 inline int read(register int x=0,register char ch=getchar(),register int f=0){
32     for(;!isdigit(ch);ch=getchar()) f=ch==‘-‘;
33     for(; isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
34     return f?-x:x;
35 }
36 int main(){
37     n=read(); k=read();
38     for(int i=1;i<=n;++i) f[i].first=read(),f[i].second=read();
39     sort(f+1,f+n+1); int ans=-1;
40     for(int i=pw[0]=1;i<=8;++i) pw[i]=pw[i-1]*133331;
41     for(int i=1;i<=n;++i) ++cnt[f[i].second][i];
42     for(int i=1;i<=8;++i) for(int j=1;j<=n;++j) cnt[i][j]+=cnt[i][j-1];
43     mp[0]=f[1].first;
44     for(int i=1;i<=n;++i){
45         for(int j=lst[f[i].second];j<i;++j){
46             int x=calc(j,i-1),t=x|(1<<f[i].second-1); mp[solve(j,x)]=-1;
47             int &val=mp[solve(j,t)]; if(val==-1) val=f[j+1].first;
48         }
49         lst[f[i].second]=i;
50         for(int j=1;j<=8;++j) t[j]=make_pair(lst[j],j);
51         sort(t+1,t+9); reverse(t+1,t+9);
52         for(int j=1,now=0;j<=8&&t[j].first;++j){
53             now|=1<<t[j].second-1;
54             if(j>=k&&mp[solve(i,now)]!=-1) ans=max(ans,f[i].first-mp[solve(i,now)]);
55         }
56         mp[0]=f[i+1].first;
57     }
58     printf("%d\n",ans);
59     return 0;
60 }

T2

C. 佛罗里达

刚开始想的是只需要判定是否为二分图,然后想用并查集来维护这个东西,然后发现有些东西没法搞。

考虑枚举答案$da$,$db$,满足$da<db$。

对于边权$w<=da$,可以忽略。

对于边权$w>db$,要将所连的点放入不同的集合。

对于边权$da<w<=db$,所连的点应满足二者都在$B$中,或二者一个在$A$中,而另一个在$B$中。

并查集维护前两种情况是简单的,但是对于第三种就伪了。

注意第三种情况可以转化为$u,v$至少一个在$B$中,这一步是考试时没想到的。

于是问题可以用2-sat解决,定义选$B$为$1$,那么情况二对应着$u$ $xor$ $v=1$,情况三对应着$u$ $or$ $v=1$。

容易发现对于确定的$db$,一个$da$是否成立具有单调性,于是可以二分判断。

还有很大的优化空间。

这里抛出一个结论:只需要考虑$db$对应最大生成树上的边 和 $A$与$B$分别对应最大生成树上的黑点和白点。

考虑首先生成最大生成树并黑白染色。

如果集合$B$中同时含有黑点和白点,那么如果$db$不为最大生成树上边,原图会形成一个偶环,这样环上一定存在一条边使得这条边权大于$db$,所以$db$为最大生成树上的边。

否则,可以认为集合$B$中只含有黑点,特判这种情况就可以了。

原文地址:https://www.cnblogs.com/skyh/p/12249553.html

时间: 2024-08-30 14:33:51

省选模拟13 题解的相关文章

省选模拟6 题解

A. Yist 首先考虑怎样的情况答案是不收敛的. 操作中涉及到对一个权值非$0$,并且不作除法的点的加法贡献. 因为只要最终的答案,可以想到对每个点作为出边的贡献分别处理. 部分分提示求出第一次迭代的贡献,发现对于每个点,贡献都是一个等比数列,所以只要代入求和公式就好了. 然而暴力做的复杂度是$O(mk)$的,会被菊花图的数据卡掉. 考虑如何优化这个东西,根据套路我们将点按照度数分块. 定义度数大于$\sqrt m$的点为重点,度数小于等于$\sqrt m$的点为轻点. 分别讨论: 对于对轻点

省选模拟七 题解

写在前面: 这次考试的策略还是蛮正确的 发现了$T2$是水题后先开了$T3$的$60pts$暴力 剩下时间连打带调外加考场刚好用完时间 但可惜的是$T1dp$求两点之间最小代价由于转移出环被弃掉了 其实用$bfs$求最小代价就可以$AC$了 实力不济 就没什么好说的 A. 翻转硬币 标签: $bfs+$状压$dp$ 题解: 先对序列差分 问题转化为每次可以同时异或两个点,求最小代价 同时消去两个点的代价可以用$bfs$预处理出来 源点的个数就是差分序列的$1$的个数 有了这个,状态便有了明显的层

[考试反思]0130省选模拟13:悔恨

0+30+20=50.rk8 关键在于: T1写错个变量名挂了100分 kxkxkxkx(激动的语无伦次) 考试过程?上来看T1,一个比较裸的基环树dp,断开环上一条边之后大概就是一个稍加改动的最大独立集. 思路不难想,细节倒是有一点,考场上调啊调啊过了样例又手模了各种数据都过了两个半小时之后很开心就扔了. 然后看T2/3啥都不会,写了俩随机化就走了. 然而T3随机化+贪心是可以AC的.正确性不知道...没写... 最后还有5分钟回T1,突然发现T1可以不是基环树而是基环树森林??? 啊修锅修锅

省选模拟五 题解

写在前面: 我好菜啊 伯努利数和自然数幂和的式子都能忘 A. 青蛙 标签: 贪心+二分 题解: 首先我们贪心的让尽量多的青蛙免费跳过去,可以二分求出 考虑剩下的青蛙如何让费用最小: 假如免费的青蛙非零,那么一定可以把中间的石头跳完 这种情况下其他每个青蛙的最小花费一定是一次 另一种情况是没有免费的青蛙 直接让花费最小的青蛙把中间的石头跳一遍,其他的花费仍然都为一次 B. 一起自习的日子 标签: 伯努利数 题解: 我们知道伯努利数有两种$B^{-}$和$B^{+}$ 其中: $$\sum\limi

「考试」省选模拟13

在家的又一场. 状态还是一般吧. 自己扔了30分. T1 比较厉害的\(dp\),考场上想到了,结果因为细节太多就没有写(真的是多). 他其实就是个基环树dp. 我们首先断掉环上某个边,然后进行一次最大匹配的\(dp\),然后这样要求这个边必然不选. 另一种情况是这个必然选,那么这条边终点的出边必然不选,再次断那个出边 再\(dp\)一次得到答案. 考虑如何输出方案. 对于一个位置我们记录这个点的最大值出现在\(0/1\)上. 然后根据这个找到最佳方案所依赖的子节点方案. 即可输出方案了. T2

省选模拟13

A. 同桌的你 考试的时候大概一上来就会了,然而感觉非常麻烦,不想打.等到最后剩1个半小时的时候开始打,到最后也没调出来,非常自闭. 不难发现将关系连边得到的是一棵基环树,所以可以考虑断掉环上任意一条边,然后分选择这条边和不选这条边分别做一次树形dp即可. 对于输出方案,考虑记录转移的前驱,之后再dfs一遍输出答案. B. 大水题 考虑枚举每一种颜色方案,将所有颜色的数量与第一种颜色的数量做差,那么区间[i,j]合法的条件是[1,i]和[1,j]差分之后相同,可以使用hash来完成这个过程. 然

省选模拟22 题解

A. 遮天蔽日 学习了计算几何相关的很多新技巧. 求过一点$P$,圆$O$的切线:通过两点距离.半径,用反三角函数可以解得一个角度,然后就可以算了. 求直线$PQ$,与圆$O$的交点:作点$O$关于$PQ$的垂线,通过半径和垂线长度,可以算得垂足与交点的距离,然后就可以算了. 求多边形的重心:任选一点$O$,选择顺时针(逆时针)上相邻的每个点对$(P,Q)$,对横纵坐标分别加权平均,加的权为面积. 公转:使重心旋转,保持每个点与重心的相对位置不变,整个多边形的朝向不变. 因为打的不是正解,所以伪

省选模拟23 题解

这篇题解鸽了. A. Expectation B. Sequence C. Counting 原文地址:https://www.cnblogs.com/skyh/p/12309632.html

省选模拟35 题解

A. two 考虑现在要通过蓝边删掉红边. 其实等价于要找出有哪些红边,满足恰好只有一个端点在蓝边的儿子方向子树中. 考虑对蓝树跑出一个 $dfs$ 序来,那么问题转化为恰好一个端点在给定区间中. 这像是一个二维偏序问题.考虑以线段树下标为其中的第一维,第二维进行排序处理. 然后用一个 $set$ 就可以简单维护了,但是这样做的复杂度是两个 $log$ 的. 考虑一个特殊的操作,开两棵线段树,第一棵以连接两个点中小的 $dfs$ 序为下标,大的为权值,第二棵则相反. 那么问题就转化为取一段前缀或