noip模拟21[Median·Game·Park]
时间:2021-07-21
本文章向大家介绍noip模拟21[Median·Game·Park],主要包括noip模拟21[Median·Game·Park]使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
\(noip模拟21\;solutions\)
这我也不知道咋了,考试就挺没欲望,看见啥题都只会打暴力,
然后就考挂了,
要有状态,集训的时候绝对不能松懈
\(T1\;Median\)
这个题,他就有点傻逼,真的太傻逼了,\(O(nlogn)\)过不了\(O(n^2)\)能过
题解告诉我啥这些数据是伪随机的,分布极其均匀,所以中位数的变化是常数级的,所以\(O(n^2)\)变\(O(n)\)???
正常的话,这个题可以用nth_element、各种平衡树、各种高级的STL都可以达到很小的复杂度,可是你比不过\(O(n^2)\)
真的,看到题解的时候我要气死了,就是存一个桶,因为有模数,然后记录一下中位数以及他的排名就好了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=1e7+5;
int n,k,w;
int prime[N],cnt;
bitset<N*18> vis;
int s1[N],s2[N];
double ans;
int now[N],sum[N*2];
signed main(){
scanf("%d%d%d",&n,&k,&w);
for(re i=2;cnt<=n;i++){
if(!vis[i])prime[++cnt]=i;
for(re j=1;j<=cnt&&prime[j]*i<=n*18;j++){
vis[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
for(re i=1;i<=n;i++)s1[i]=1ll*i*prime[i]%w;
for(re i=1;i<=n;i++)s2[i]=s1[i]+s1[i/10+1];
if(k&1){
for(re i=1;i<=k;i++)sum[s2[i]]++,now[i]=s2[i];
sort(now+1,now+k+1);
int mid=now[k+1>>1],rak=0;
for(re i=1;i<=k;i++)
if(now[i]<=mid)rak++;
ans+=mid;
for(re i=2;i<=n-k+1;i++){
if(s2[i-1]<=mid)rak--;
if(s2[i+k-1]<=mid)rak++;
sum[s2[i-1]]--;
sum[s2[i+k-1]]++;
while(rak-sum[mid]>=(k+1>>1))rak-=sum[mid],mid--;
while(rak+sum[mid+1]<(k+1>>1))rak+=sum[mid+1],mid++;
if(rak<(k+1>>1))mid++,rak+=sum[mid];
ans+=mid;
}
}
else{
for(re i=1;i<=k;i++)now[i]=s2[i],sum[s2[i]]++;
sort(now+1,now+k+1);
int m1,r1=0,m2,r2=0;
m1=now[k>>1];m2=now[k+2>>1];
for(re i=1;i<=k;i++){
if(now[i]<=m1)r1++;
if(now[i]<=m2)r2++;
}
//cout<<r2<<endl;
ans+=(m1+m2)*1.0/2.0;
for(re i=2;i<=n-k+1;i++){
//cout<<i<<endl;
sum[s2[i-1]]--;
sum[s2[i+k-1]]++;
if(s2[i-1]<=m1)r1--;
if(s2[i-1]<=m2)r2--;
if(s2[i+k-1]<=m1)r1++;
if(s2[i+k-1]<=m2)r2++;
while(r1-sum[m1]>=(k>>1))r1-=sum[m1],m1--;
while(r1+sum[m1+1]<(k>>1))r1+=sum[m1+1],m1++;
if(r1<(k>>1))m1++,r1+=sum[m1];
while(r2-sum[m2]>=(k+2>>1))r2-=sum[m2],m2--;
while(r2+sum[m2+1]<(k+2>>1))r2+=sum[m2+1],m2++;//cout<<r2<<endl;
if(r2<(k+2>>1))m2++,r2+=sum[m2];
ans+=(m1+m2)*1.0/2.0;
}
}
printf("%.1lf",ans);
}
·
\(T2\;Game\)
呵呵呵,这个题更傻逼,傻逼到爆炸,就是一傻逼题
排序不用优先队列???,凭啥你这数的范围是1-n
凭啥???凭啥????凭啥可以用桶???
考完就5min就Ac这个题,要是我看到了数据范围,我至于只有5pts
还不只这些,这个傻逼题,它让你求差,凭啥差是负数,这是我语文不好还是你语文不好啊,不需要绝对值??
真是考个试能吧我给气死
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e5+5;
int n,K,a[N];
ll sco[2],sum[N];
signed main(){
scanf("%d%d",&n,&K);
for(re i=1;i<=n;i++)scanf("%d",&a[i]);
while(K--){
sco[0]=sco[1]=0;
int p,maxn=0,now=0;scanf("%d",&p);
for(re i=1;i<p;i++)sum[a[i]]++,maxn=max(maxn,a[i]);
for(re i=p;i<=n;i++){
if(a[i]>=maxn)sco[now]+=a[i];
else{
sum[a[i]]++;
sum[maxn]--;
sco[now]+=maxn;
while(sum[maxn]==0)maxn--;
}now^=1;
}
for(re i=maxn;i>=1;i--)
while(sum[i]){
sco[now]+=i;
now^=1;sum[i]--;
}
printf("%lld\n",sco[0]-sco[1]);
}
}
·
\(T3\;Park\)
这个题还是非常有水平的,我连dfs都没有想到啊,气死了
首先有一个性质,在确定根的情况下,我在某个节点放一个面包屑,那么它对答案的贡献就是它的子节点的权值之和
所以我们dfs的时候要先预处理以1为根的时候的siz,贡献
利用两个数组,一个f[i][j]维护从i向它的子树走,一个g[i][j]由子树向他走,i表示那个节点,j表示撒了几个面包
然后就像求树上直径一样的,像点分治一样的,两两一加就好了,但是注意这个f,g是有方向的
所以我们要按照遍历儿子的顺序,正着一遍,倒着一遍
记得赋初值
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int n,V,p[N];
int to[N*4],nxt[N*4],head[N],heed[N],rp;
ll f[N][105],g[N][105],siz[N];
//ll maxf[205],maxg[205];
ll ans;
void add_edg1(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
void add_edg2(int x,int y){
to[++rp]=y;
nxt[rp]=heed[x];
heed[x]=rp;
}
void dfs(int x,int fa){
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa)continue;
siz[x]+=p[y];
}
for(re i=head[x];i;i=nxt[i])
if(to[i]!=fa)dfs(to[i],x);
for(re i=1;i<=V;i++)f[x][i]=siz[x],g[x][i]=siz[x]+p[fa];
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa)continue;
for(re j=1;j<=V;j++)ans=max(ans,g[x][j]+f[y][V-j]);
for(re j=1;j<=V;j++)g[x][j]=max(g[x][j],max(g[y][j],g[y][j-1]+siz[x]-p[y]+p[fa]));
for(re j=1;j<=V;j++)f[x][j]=max(f[x][j],max(f[y][j],f[y][j-1]+siz[x]));
}
for(re i=1;i<=V;i++)f[x][i]=siz[x],g[x][i]=siz[x]+p[fa];
for(re i=heed[x];i;i=nxt[i]){
int y=to[i];
if(y==fa)continue;
for(re j=1;j<=V;j++)ans=max(ans,g[x][j]+f[y][V-j]);
for(re j=1;j<=V;j++)g[x][j]=max(g[x][j],max(g[y][j],g[y][j-1]+siz[x]-p[y]+p[fa]));
for(re j=1;j<=V;j++)f[x][j]=max(f[x][j],max(f[y][j],f[y][j-1]+siz[x]));
}
}
signed main(){
scanf("%d%d",&n,&V);
for(re i=1;i<=n;i++)scanf("%d",&p[i]);
for(re i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
add_edg1(x,y);add_edg1(y,x);
}
for(re i=1;i<=n;i++)
for(re j=head[i];j;j=nxt[j])
add_edg2(i,to[j]);
//for(re i=1;i<=n;i++)f[i][0][1]=g[i][0][1]=-inf;
dfs(1,0);
printf("%lld",ans);
}
原文地址:https://www.cnblogs.com/hzoi-fengwu/p/15038624.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- View事件分发、滑动冲突 详解
- Python Django开发 异常及其解决办法(一)
- 带你彻底搞懂-View的工作原理!
- Python 批量下载BiliBili视频 打包成软件
- 必要掌握!Window、WindowManager !
- 面试必备:ThreadLocal+Looper+Handler
- 子线程 真的不能更新UI ?
- Web前端开发 HTML设计 经验与技巧总结
- [OHIF-Viewers]医疗数字阅片-医学影像-辅助工具-Redux DevTools-DevTools for Redux with hot reloading, action replay,
- 全面理解:Android中的线程及线程池
- Ubuntu系统 安装与配置 常见异常与解决办法
- [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-中二-Redux&react-redux状态管理详解
- Bitmap的加载和Cache
- Python全栈 Linux基础之2.Linux终端命令简介
- Ubuntu系统 使用与开发 常见异常与解决办法