\(ZJOI2022\)

众数

发现并不存在\(poly(log(n))\)的做法,那么尝试\(n\sqrt n\)

套路的按照出现次数分组,分为大于\(\sqrt n\)和小于\(\sqrt n\)

然后分别维护,小数对小数的贡献为什么要算两次,我们贡献是一段区间众数\(-\)这个数出现次数,是因为貌似一边连续从开始一段颜色需要考虑

//根号分治比较显然,分块维护不是很可行
//出现次数大于根号n,最多有根号n个,然后枚举哪些颜色变成这个颜色
//然后找一个合适的位置转移过去
//出现次数小于根号,枚举变化位置即可
//我们的贡献计算方式分为
//大于根号的向大于根号的贡献
//大于根号的向小于根号的贡献
//小于根号的向大于根号的贡献
//小于根号的向小于根号的贡献
//前三种都在第一次处理时解决
//考虑怎么贡献,我们可以枚举对别的的贡献
//那么我们每次暴力修改一段区间,更新内部的
//我们Max求的一直是,我们能最多多多少
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
int a[MAXN],b[MAXN],t[MAXN],bc[MAXN],sum[MAXN],Max[MAXN],Lim,tot,n;
vector<int>poz[MAXN];
map<int,int>mp;
void solve()
{
for(int i=1;i<=n;i++) sum[i]=0;
for(int i=1;i<=n;i++)
{
if(t[a[i]]<=Lim)
{ int p=lower_bound(poz[a[i]].begin(),poz[a[i]].end(),i)-poz[a[i]].begin();
//我们这一步只需要求区间众数就好了
//贡献就是区间众数-本数字出现次数
// cout<<"now: "<<a[i]<<" "<<i<<" "<<p<<"\n";
for(int j=p,l,r;j>=0;j--)
{
if(j==0) l=1;
else l=poz[a[i]][j-1]+1;
r=poz[a[i]][j];
// cout<<j<<" "<<poz[a[i]].size()<<" "<<l<<" "<<r<<"\n";
Max[a[i]]=max(Max[a[i]],sum[l]-(p-j));
while(l<=r&&sum[r]<p-j+1) sum[r--]=p-j+1;
}
}
}
}
void sol()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
mp.clear();tot=0;
memset(t,0,sizeof(t));
memset(bc,0,sizeof(bc));
memset(Max,0,sizeof(Max));
for(int i=1;i<=n;i++) poz[i].clear();
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{
if(!mp[b[i]]) mp[b[i]]=++tot,bc[tot]=b[i];
// t[mp[b[i]]]++;
// poz[mp[b[i]]].push_back(i);
}
for(int i=1;i<=n;i++) a[i]=mp[a[i]],t[a[i]]++,poz[a[i]].push_back(i);
Lim=sqrt(n);
for(int i=1;i<=tot;i++)
{
if(t[i]>Lim)
{
sum[0]=0;
for(int j=1;j<=n;j++)
{
sum[j]=sum[j-1]+(int)(a[j]==i);
}
int l=0,s=0;
//我们其余的对当前贡献相当于一个最大子段和
for(int j=1;j<=tot;j++)
{
int N=t[j],l=0,r,s=0;
for(int k=0;k<N;k++)
{
r=poz[j][k];
s=max(0,s-(sum[r]-sum[l]))+1;
Max[i]=max(Max[i],s);
l=r;
}
l=s=0;
for(int k=0;k<N;k++)
{
r=poz[j][k];
s=max(s,0)+sum[r]-sum[l];
Max[j]=max(Max[j],s--);
l=r;
}
}
}
}
solve();
reverse(a+1,a+1+n);
for(int i=1;i<=tot;i++)
{
reverse(poz[i].begin(),poz[i].end());
for(int j=0;j<poz[i].size();j++) poz[i][j]=n-poz[i][j]+1;
}
solve();
int Ans=0;
for(int i=1;i<=tot;i++)
{
Max[i]+=t[i];
Ans=max(Ans,Max[i]);
}
cout<<Ans<<"\n";
for(int i=1;i<=tot;i++)
{
if(Max[i]==Ans) cout<<bc[i]<<"\n";
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--) sol();
}

\(T2\)

计数题滚出OI

一道(对我)并不签到的(对大家而已的)签到题

首先我们可以枚举\(2^n\)的状态,表示第一个树的叶子集合,然后方案也比较好求

树的形态就是在保证每个点找一个前面的点然后把叶子不对的容斥出去,子集容斥就好了\(?\)

\(O(2^n n)\)的暴力直接枚举两树形态,转移时候直接把非叶子节点标记为\(1\)即可

然后发现合并的时候\(dp[n][x]=dp[n][x_{rev}]\)

就很\(nb\)了,意思就是,我们得到了两棵树状态确定之后,他们的情况数是相同的

我们就先确定一个树的状态

\(f(S)\)为恰好\(S\)不是叶子的方案数

\(g(S)\)为钦定除了\(S\)之外的点都是叶子(\(S\)之内可是可不是)的方案数

\(g(S)\)易得

\(g(S)=\Pi_{i=2}^n\sum_{j\in S}[j<i]\)

直接枚举前面的可以成为非叶子的去选

\(f(S)=\sum_{T\subset S,1\not\in T}(-1)^{|T|}g(S\backslash T)\)

我们要求\(\sum_S f^2(S)\)

需要拆开计算

\(\large\sum_S f^2(S)=\sum_S\sum_{T_1\in S}\sum_{T_2\in S}(-1)^{|T_1|+|T_2|}\large(\small \Pi_{i=2}^n\sum_{j\in S\backslash T_1}[j<i]\large)\large(\small \Pi_{i=2}^n\sum_{j\in S\backslash T_2}[j<i]\large)\)

化简一下

\(\sum_{S}\sum_{T_1\in S}\sum_{T_2\in S}(-1)^{|T_1|+|T_2|}\Pi_{i=2}^n (\sum_{j\in S\backslash T_1 [j<i]})(\sum_{j\in S\backslash T_1} [j<i])\)

到这就可以\(dp\)了

具体的话,我们仅需要枚举我们当前的\(i\)在哪些里面做贡献就好了,把后面两个\(\sum\)压入状态

#include<bits/stdc++.h>
#define int long long
#define MAXN 505
using namespace std;
int dp[2][MAXN][MAXN];
int n,mod;
signed main()
{
scanf("%lld%lld",&n,&mod);
dp[0][1][1]=1;
for(int i=1;i<n;i++)
{
int now=i%2;
int pre=now^1;
memset(dp[now],0,sizeof(dp[now]));
for(int j=1;j<=i;j++)
{
for(int k=1;k<=i;k++)
{
int val=dp[pre][j][k]*j%mod*k%mod;
dp[now][j][k]+=2*val;
dp[now][j+1][k+1]+=val;
dp[now][j+1][k]-=val;
dp[now][j][k+1]-=val;
}
}
int Ans=0;
for(int j=1;j<=i+1;j++)
{
for(int k=1;k<=i+1;k++)
{
(Ans+=dp[now][j][k])%=mod;
}
}
cout<<(Ans+mod)%mod<<"\n";
}
}

最新文章

  1. 【腾讯Bugly干货分享】Android动态布局入门及NinePatchChunk解密
  2. java从基础知识(七)java集合
  3. 关于变量和函数前&amp;符号的作用
  4. Foundation 6 – 先进的响应式的前端开发框架
  5. (一)u-boot-nand.bin的下载
  6. hibernate笔记加强版
  7. Android企业级程序完全退出的解决方案【转】
  8. POJ 1328 Radar Installation#贪心(坐标几何题)
  9. Android Studio基本配置
  10. Linux二进制安装apache2.4.25
  11. 20165305 《网络对抗技术》 Kali安装
  12. 201806 数据处理 SQL、python、shell 哪家强...速度PK(上篇)
  13. Android NDK笔记
  14. fiddler电脑抓包和手机抓包
  15. Notyf - 超级简单、响应式的 JS 通知插件
  16. android post 方式 访问网络 实例
  17. html----属性操作
  18. Robotframework 之常用断言关键字简介
  19. 利用vbs设置Java环境变量
  20. POJ 1163 The Triangle DP题解

热门文章

  1. 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表
  2. 859. Buddy Strings - LeetCode
  3. OAuth2.0之OLTU实现举例
  4. Linux用户权限集中管理方案
  5. 130_传析阅管理系统accdb64位版本
  6. 117_PowerQuery使用ODBC访问带密码的Access
  7. css3常用动画
  8. df-查看磁盘目录空间大小
  9. 在windows下使用s3cmd和s3browser来管理amazon s3的笔记
  10. 『忘了再学』Shell基础 — 24、Shell正则表达式的使用