A.Median

这题的数据生成方式并没有什么规律,所以可以认为是随机数据。

维护一个桶,表示当前K长区间里的值域情况。

并且用变量记录中位数值域上的左侧有多少个数,当区间调整时一并调整桶和这个变量即可。

由于是随机数据,所以每次的调整幅度并不会很大,近似于常数。

复杂度$O(n)$。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e7+2;
int n,K,bu[N<<1];
ll ans=0;
int mod,a[N],b[N];
int pr[12000000],tot;
bool vis[200000005];
void ini()
{
for(int i=2;i<=190000000;i++)
{
if(!vis[i])pr[++tot]=i;
for(int j=1;j<=tot&&i*pr[j]<=190000000;j++)
{
vis[i*pr[j]]=1;
if(i%pr[j]==0)break;
}
}
} int main()
{
ini();//cout<<tot<<endl;
scanf("%d%d%lld",&n,&K,&mod);
for(int i=1;i<=n;i++)
a[i]=pr[i]*1LL*i%mod,b[i]=a[i]+a[i/10+1];
for(int i=1;i<=K;i++)
bu[b[i]]++;
int lpos=K-1>>1,rpos=K>>1,cnt=0;
int p=0;
while(cnt<=lpos)cnt+=bu[p++];
p--;
for(int i=1;i+K-1<=n;i++)
{
int _p=p,_cnt=cnt;
while(_cnt<=rpos)_cnt+=bu[++_p];
ans+=p+_p;
bu[b[i]]--;bu[b[i+K]]++;
if(b[i]<=p)cnt--;
if(b[i+K]<=p)cnt++;
while(cnt<=lpos)cnt+=bu[++p];
while(cnt-bu[p]>lpos)cnt-=bu[p--];
//cout<<p<<endl;
}
cout<<ans/2<<(ans&1?".5":".0")<<endl;
return 0;
}

B.Game

显然,最优策略即每次都选自己能选的最大的。

同样维护桶,表示当前可选集合内的值域情况。维护一个变量,表示这个集合内可选最大值。

如果要保证复杂度,就应当使这个变量整个过程中在值域上的跳动幅度不超过n。

所以每当一个新数加入集合,判断它和最大值的关系,如果大于最大值就直接被选走。反之把新数加入桶,最大值被选走,暴力跳值域找到新的最大值。

很容易发现这样最大值指针是单调不增的。

时间复杂度$O(nk)$。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
typedef long long ll;
int n,a[N],K,P,b[N],key[N],bu[N];
ll ans[2];
void work()
{
P=read();
ans[0]=ans[1]=0;
int now=0;
for(int i=1;i<=P;i++)
bu[a[i]]++,now=max(now,a[i]);
int p=P+1,who=0;
bu[now]--;ans[who]+=key[now];
while(!bu[now])now--;
for(int t=2;t<=n;t++)
{
who^=1;
if(a[p]>=now)ans[who]+=key[a[p]];
else
{
bu[a[p]]++,bu[now]--,ans[who]+=key[now];
while(!bu[now])now--;
}
p++;
}
printf("%lld\n",ans[0]-ans[1]);
}
int main()
{
// freopen("g.in","r",stdin);
n=read();K=read();
for(int i=1;i<=n;i++)
a[i]=read(),b[i]=a[i];
sort(b+1,b+n+1);
int len=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)
{
int now=lower_bound(b+1,b+len+1,a[i])-b;
key[now]=a[i];
a[i]=now;
}
while(K--)work();
return 0;
}

C.Park(CEOI2017 Chase)

思路很棒的dp。设$w[x]$为$x$的点权(铁球数),$al[x]$为与$x$相连所有点的点权和。

不难发现,每选择一个点扔下磁铁,就会对答案产生$al[x]-w[fa]$的贡献。

我们要求的是一条有序路径,不妨把它分成从下往上和从上往下两部分。

设$dp[x][i][0]$为从下往上走到x,使用了i个磁铁的最大贡献,$dp[x][i][1]$为从x往下走,使用i个磁铁的最大贡献。

这样就可以区分上一步从哪里来。

之后考虑怎么dp。首先向下dfs,在回溯过程中将儿子y的贡献计入x。注意要先把$dp[x]...$初始化为单点的贡献,先用它与$dp[y]...$拼接起来更新一下答案再进行转移。

$dp[x][i][0]=\max (dp[y][i][0],dp[y][i-1][0]+al[x]-w[y])$

$dp[x][i][1]=\max (dp[y][i][1],dp[y][i-1][1]+al[x]-w[fa])$

因为路径是有序的,所以$S \rightarrow T$与$T \rightarrow S$是不同的。需要把儿子顺序反转后再更新一遍。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=1e5+5;
typedef long long ll;
int n,val,w[N];
int to[N<<1],head[N],nxt[N<<1],tot;
ll dp[N][102][2],al[N],ans;
//0 down to up
//1 up to down
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void up(int x,int y,int f)
{
for(int i=1;i<val;i++)
ans=max(ans,dp[x][i][0]+dp[y][val-i][1]);
for(int i=1;i<=val;i++)
{
ll maxx=max(dp[y][i][0],dp[y][i-1][0]+al[x]-w[y]);
dp[x][i][0]=max(dp[x][i][0],maxx);
maxx=max(dp[y][i][1],dp[y][i-1][1]+al[x]-w[f]);
dp[x][i][1]=max(dp[x][i][1],maxx);
}
}
void dfs(int x,int f)
{
stack<int> son;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)continue;
son.push(y);
dfs(y,x);
}
for(int i=1;i<=val;i++)
dp[x][i][0]=al[x],dp[x][i][1]=al[x]-w[f];
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)continue;
up(x,y,f);
}
for(int i=1;i<=val;i++)
dp[x][i][0]=al[x],dp[x][i][1]=al[x]-w[f];
while(!son.empty())
up(x,son.top(),f),son.pop();
ans=max(ans,max(dp[x][val][0],dp[x][val][1]));
} int main()
{
n=read();val=read();
for(int i=1;i<=n;i++)
w[i]=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
for(int x=1;x<=n;x++)
for(int i=head[x];i;i=nxt[i])
al[x]+=w[to[i]];
dfs(1,0);
cout<<ans<<endl;
return 0;
}

[CSP-S模拟测试63]题解的更多相关文章

  1. CSP-S 模拟测试94题解

    T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...

  2. CSP-S模拟测试 88 题解

    T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...

  3. CSP-S 模拟测试92 题解

    话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...

  4. CSP-S 模拟测试57题解

    人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...

  5. CSP-S 模拟测试 51 题解

    考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...

  6. CSP-S 模拟测试 45 题解

    由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...

  7. [CSP-S模拟测试97]题解

    A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...

  8. [CSP-S模拟测试96]题解

    以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘 ...

  9. [CSP-S模拟测试92]题解

    A.数列 显然每个数的答案是互相独立的,直接扩欧求解.我们需要最小化$ax+by=gcd(a,b)$中的$|x|+|y|$,而显然当x或y靠近0时答案可能最优,列个不等式求一下即可. 能$O(1)$千 ...

随机推荐

  1. C#编写ActiveX控件

    用C#编写ActiveX控件 http://www.cnblogs.com/homer/archive/2005/01/04/86473.html http://www.cnblogs.com/hom ...

  2. Dllregisterserver调用失败解决方法

    在做一个注册com组件时,出现这样的情况 出现这个错误一般是和权限问题有关,命令提示符需要以管理员权限运行才可以注册成功. 最简单的解决方法就是: 在开始菜单右击—>命令提示符(管理员)(A) ...

  3. Windows Server服务器之用户界面,任务管理器等

    用户界面简化服务器管理.跟Windows 8一样,重新设计了服务器管理器,采用了Metro界面(核心模式除外).在这个Windows系统中,PowerShell已经有超过2300条命令开关(Windo ...

  4. [CSP-S模拟测试]:赤壁情(DP)

    前赤壁赋 壬戌之秋,七月既望,苏子与客泛舟游于赤壁之下.清风徐来,水波不兴.举酒属客,诵明月之诗,歌窈窕之章.少焉,月出于东山之上,徘徊于斗牛之间.白露横江,水光接天.纵一苇之所如,凌万顷之茫然.浩浩 ...

  5. mysql创建,添加主键

    primary key 1.最简单的: CREATE TABLE t1( id int not null, name char(20)); 2.带主键的: a:CREATE TABLE t1( id ...

  6. PHP的Session机制解析 2

    在鸟哥的博客看到对php session的过期时间的一篇文章,在此记录. 原文地址:http://www.laruence.com/2012/01/10/2469.html 以下是鸟哥博客原文: 今天 ...

  7. [MAC]配置Jenkins 开机自启动

    如果是将jenkins.war放在tomcat中运行的, 则可以配置开机启动tomcat,脚本如下: XXX表示是你安装Tomcat所在目录 #启动tomcat cd XXX/Tomcat8/bin ...

  8. spring4.1.8扩展实战之二:Aware接口揭秘

    Aware.java是个没有定义任何方法的接口,拥有众多子接口,在spring源码中有多处都在使用这些子接口完成各种场景下的回调操作,当业务有需要时,我们只需创建类来实现相关接口,再声明为bean,就 ...

  9. Python 进阶_闭包 & 装饰器

    目录 目录 闭包 函数的实质和属性 闭包有什么好处 小结 装饰器 更加深入的看看装饰器的执行过程 带参数的装饰器 装饰器的叠加 小结 装饰器能解决什么问题 小结 闭包 Closure: 如果内层函数引 ...

  10. drf基础

    1.什么是编程? 数据结构和算法的结合 2.什么是REST? 同一个功能会产生五花八门的url(把查看单条记录和查看多条记录都看成是一个功能),而且响应回去的数据也没有同一的格式规范,这就造成了前后端 ...