NOIP模拟测试14
考完19了再写14,我也是够咕的。
14的题很好,也充分暴露了我的问题。
T1是个分析性质推结论的题
对于区间[L,R],不妨设a[L]!=a[R],那么两个端点对答案没有贡献,也就是[L+1,R],[L,R-1]都是符合题意的区间。
即 最优的区间的两个端点一定相等
然后把每个数的位置和大小作为区间的两端点,统计答案即可。
#include<bits/stdc++.h>
#define F(n) for(int i=1;i<=n;i++)
int a[],sum[],n,ans;
std::vector< std::pair<int,int> >k[<<];
int main(){
scanf("%d",&n);
F(n)scanf("%d",&a[i]),sum[i]=sum[i-]+(a[i]==i);ans=sum[n];
F(n)k[a[i]+i].push_back(std::make_pair(std::min(i,a[i]),std::max(i,a[i])));
F((n<<))sort(k[i].begin(),k[i].end());
F((n<<))
for(int t=k[i].size(),j=t-,last=;j>=;j--,last++)
ans=std::max(ans,last++sum[k[i][j].first-]+sum[n]-sum[k[i][j].second]);
std::cout<<ans;
}
T2走格子
关键在于如何将题目抽象成图论模型,而不是只一味的搜索。
这道题没有太多的限制,只有移动到每个格子的距离的不同。
因此直接建边,跑dijstra即可
#include<bits/stdc++.h>
#define MAXN 505
using namespace std;
const int h[]={,,-,,},l[]={,,,,-};
int mp[MAXN][MAXN],endx,endy,n,m,tot=;
priority_queue<pair<int,int> >Q;
vector<int>zh[MAXN],zl[MAXN];
bool vst[MAXN*MAXN];
int ans=0x7f7f7f7f,stax,stay;
int p[MAXN][MAXN],d[MAXN*MAXN],nxt[MAXN*MAXN*],val[MAXN*MAXN*],to[MAXN*MAXN*],cnt,head[MAXN*MAXN];
void add(int u,int v,int w)
{
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;val[cnt]=w;
return ;
}
int dijstra()
{
memset(d,0x3f,sizeof(d));d[p[stax][stay]]=;
Q.push(make_pair(,p[stax][stay]));
while(Q.size())
{
int k=Q.top().second;Q.pop();
if(k==p[endx][endy])return d[k];
if(vst[k])continue;
vst[k]=;
for(int i=head[k];i;i=nxt[i])
{
int y=to[i];
if(d[y]>d[k]+val[i])
{
d[y]=d[k]+val[i];
Q.push(make_pair(-d[y],y));
}
}
}
return 0x7f7f7f7f;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
p[i][j]=++tot;
char c=getchar();
while(c!='C'&&c!='F'&&c!='.'&&c!='#')c=getchar();
if(c=='C')stax=i,stay=j,mp[i][j]=;
else if(c=='F')endx=i,endy=j,mp[i][j]=;
else if(c=='.')mp[i][j]=;
else mp[i][j]=;
}
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(!mp[i][j])zh[i].push_back(j);
for(int j=;j<=m;j++)
for(int i=;i<=n;i++)
if(!mp[i][j])zl[j].push_back(i);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(!mp[i][j])continue;
if(i^&&mp[i-][j])add(p[i][j],p[i-][j],);
if(i^n&&mp[i+][j])add(p[i][j],p[i+][j],);
if(j^&&mp[i][j-])add(p[i][j],p[i][j-],);
if(j^m&&mp[i][j+])add(p[i][j],p[i][j+],);
int up=*(--lower_bound(zl[j].begin(),zl[j].end(),i));
int down=*(lower_bound(zl[j].begin(),zl[j].end(),i));
int lef=*(--lower_bound(zh[i].begin(),zh[i].end(),j));
int rig=*(lower_bound(zh[i].begin(),zh[i].end(),j));
int dis=min(i-up,min(down-i,min(j-lef,rig-j)));
add(p[i][j],p[up+][j],dis);
add(p[i][j],p[down-][j],dis);
add(p[i][j],p[i][lef+],dis);
add(p[i][j],p[i][rig-],dis);
}
ans=dijstra();
if(ans==0x7f7f7f7f)cout<<"no"<<endl;
else cout<<ans<<endl;
return ;
}
T3柱状图 好题标记
这道题考察的是三分。
观察一下可知对于某一位置来说,其高度大小与最终答案的关系是单谷的。
(当你得到一个最优答案的时候,如果变大会使其余的柱子在原基础上再上升一个,反之亦然)
于是60分做法诞生:
枚举位置,三分高度,统计答案 O(n^2logn)
#include<bits/stdc++.h>
#define MAXN 100005
#define int long long
#define F(x) for(int i=1;i<=n;i++)
#define re register
#define min(a,b) (a)<(b)?(a):(b)
using namespace std;
int a[MAXN],now,n,maxn;
inline int Get(int h)
{
int ans=abs(h-a[now]);
F(n)
{
if(i==now)continue;
if(h-abs(i-now)<=)return 0x7f7f7f7f7f7f7ff;
ans+=abs(a[i]-(h-abs(i-now)));
}
return ans;
}
inline int San_fen()
{
int l=now,r=maxn*;
while(l+<r)
{
int lmid=l+(r-l)/;
int rmid=r-(r-l)/;
if(Get(lmid)<Get(rmid))r=rmid;
else l=lmid;
}
return min(Get(l),min(Get(l+),Get(l+)));
}
signed main()
{
re int ans=0x7f7f7f7f7f7f7ff;
scanf("%lld",&n);
F(n)scanf("%lld",&a[i]),maxn=max(maxn,a[i]);
for(now=;now<=n;now++)
ans=min(ans,San_fen());
cout<<ans<<endl;
return ;
}
考虑优化,对于统计答案,我们分情况讨论一下
(讨论个毛线)详情见这里
主要说一下skyh的垃圾退火(雾)
模拟退火是一个特别神(kan)奇(lian)的算法。
是这样的:
根据物理学常识我们可以知道,物体内能越小越稳定。
所谓的模拟退火,就是模拟这个过程。
1.设置初始温度T0
2.找出下一个目标位置
3.尝试用新的答案更新旧的答案
4.降温
是不是一脸蒙蔽?
详细来说:
while(T>eps) //终止边界
{
tmp=now+(rand()*2ll-RAND_MAX)*T*0.000001; //温度越高,变化越大
if(T<1.0)tmp=max(tmp,1ll),tmp=min(tmp,n); //当温度小于一定程度的时候,让下一个位置尽量小地变化
else tmp=(tmp%n+n)%n+; //让下一个位置在要求的范围内
tmpans=calc(tmp);D=-fabs(tmpans-nowans); //找到新的解
if(tmpans<nowans||exp(D/T)*RAND_MAX>rand())nowans=tmpans,now=tmp; //根据概率确定答案是否改变
if(tmpans<ans)ans=tmpans; //更新最终的答案
T*=0.975; //降温
}
根据前人的经验,这个更新的概率是exp(D/T)(D是变化量绝对值的相反数,T是当前温度)
最后附上完整代码
#include<bits/stdc++.h>
#define MAXN 100005
#define int long long
using namespace std;
int yx[MAXN],n,now;
struct Bit{
int tr[][MAXN];
void insert(int x,int val,int opt)
{
for(int i=x;i<=n;i+=i&-i)tr[][i]+=val,tr[][i]+=opt;
return ;
}
pair<int,int> query(int x)
{
int num=,ans=;
for(int i=x;i;i-=i&-i)num+=tr[][i],ans+=tr[][i];
return make_pair(ans,num);
}
}T[];
int sa[MAXN],sb[MAXN],ap[MAXN],bp[MAXN],ans=0x7f7f7f7f7f7f7ff,maxa,a[MAXN],b[MAXN];
inline int check(int x)
{
if(x<now||x<(n-now+))return 0x7f7f7f7f7f7f7ff;
int ans=abs(x-yx[now]);
int num=upper_bound(a+,a+n+,x-now)-a-;
pair<int,int> w=T[].query(num);
ans+=abs(w.first-w.second*(x-now))+abs(sa[now-]-w.first-(now--w.second)*(x-now));
num=upper_bound(b+,b+n+,x+now)-b-;
w=T[].query(num);
ans+=abs(w.first-(now+x)*w.second)+abs(sb[n]-sb[now]-w.first-(n-now-w.second)*(now+x));
return ans;
}
inline int san_fen()
{
int l=,r=maxa*;
while(l+<r)
{
int lmid=l+(r-l)/,
rmid=r-(r-l)/;
if(check(lmid)<check(rmid))r=rmid;
else l=lmid;
}
return min(check(l+),min(check(l+),check(l)));
}
signed main()
{
cin>>n;
for(int i=;i<=n;i++)
{
scanf("%lld",&yx[i]);
ap[i]=a[i]=yx[i]-i;
bp[i]=b[i]=yx[i]+i;
sa[i]=sa[i-]+a[i];
sb[i]=sb[i-]+b[i];
maxa=max(maxa,yx[i]);
}
sort(a+,a+n+);sort(b+,b+n+);
for(int i=;i<=n;i++)
{
ap[i]=lower_bound(a+,a+n+,ap[i])-a;
bp[i]=lower_bound(b+,b+n+,bp[i])-b;
}
for(int i=;i<=n;i++)T[].insert(bp[i],yx[i]+i,);
for(now=;now<=n;now++)
{
T[].insert(bp[now],-(yx[now]+now),-);
ans=min(san_fen(),ans);
T[].insert(ap[now],yx[now]-now,);
}
cout<<ans<<endl;
return ;
}
正解AC
#include<bits/stdc++.h>
#define MAXN 100005
#define int long long
#define re register
using namespace std;
double eps=1e-,T=,D;
int mid,n,a[MAXN],b[MAXN];
inline int calc(int x)
{
for(int i=;i<=n;i++)b[i]=a[i]+abs(i-x);
nth_element(b+,b+mid,b+n+);
re int now=max(b[mid],max(x,n-x+)),ans=;
for(int i=;i<=n;i++)
{
if(now-abs(i-x)<=)return 0x7f7f7f7f7f;
ans+=abs(now-b[i]);
}
return ans;
}
signed main()
{
srand((unsigned)time());
cin>>n;
mid=(+n)>>;
for(int i=;i<=n;i++)scanf("%lld",&a[i]);
int ans=0x7f7f7f7f7f7f;
int now=(+n>>);
int nowans=calc(now),tmp,tmpans;
while(T>eps)
{
tmp=now+(rand()*2ll-RAND_MAX)*T*0.000001;
if(T<1.0)tmp=max(tmp,1ll),tmp=min(tmp,n);
else tmp=(tmp%n+n)%n+;
tmpans=calc(tmp);D=-fabs(tmpans-nowans);
if(tmpans<nowans||exp(D/T)*RAND_MAX>rand())nowans=tmpans,now=tmp;
if(tmpans<ans)ans=tmpans;
T*=0.975;
}
cout<<ans<<endl;
return ;
}
退火AC
模拟退火是一个特别优秀的算法,请不要针对算法,(尽管你可以针对脸某)。
NOIP模拟测试14的更多相关文章
- 8.7 NOIP模拟测试14 旋转子段+走格子+ 柱状图
T1 旋转子段 30% 暴力枚举起点和长度,暴力判断,o(n3) 不知道为什么我拿了40分... 60% 每一个点都有一个固定的旋转中心可以转成固定点,枚举旋转点和长度. 100% 用一个vecto ...
- 2019.8.7 NOIP模拟测试14 反思总结
先扔代码 调完自闭网络流了,新一轮考试前看看能不能赶完…… 考得极其爆炸,心态也极其爆炸,真的是认识到自己能力上的不足 思维跑偏,代码能力差 就这样吧,再努力努力,不行就AFO T1旋转子段: 因为我 ...
- NOIP模拟测试14「旋转子段·走格子·柱状图」
旋转子段 连60分都没想,考试一直肝t3,t2,没想到t1最简单 我一直以为t1很难,看了题解发现也就那样 题解 性质1 一个包含a[i]旋转区间值域范围最多为min(a[i],i)----max(a ...
- 「题解」NOIP模拟测试题解乱写II(36)
毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组
2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色
2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)
2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...
- NOIP模拟测试17&18
NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...
- 2019.8.14 NOIP模拟测试21 反思总结
模拟测试20的还没改完先咕着 各种细节问题=错失190pts T1大约三分钟搞出了式子,迅速码完,T2写了一半的时候怕最后被卡评测滚去交了,然后右端点没有初始化为n…但是这样还有80pts,而我后来还 ...
随机推荐
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(2.1)- 玩转板载OpenSDA,Freelink调试器
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列EVK上板载调试器的用法. 本文是i.MXRT硬件那些事系列第二篇,第一篇痞子衡给大家整体介绍了i.M ...
- Spring Boot 2.x 基础案例:整合Dubbo 2.7.3+Nacos1.1.3(配置中心)
本文原创首发于公众号:Java技术干货 1.概述 本文将Nacos作为配置中心,实现配置外部化,动态更新.这样做的优点:不需要重启应用,便可以动态更新应用里的配置信息.在如今流行的微服务应用下,将应用 ...
- A-07 前向分步算法
目录 前向分步算法 一.前向分步算法引入 二.前向分步算法详解 2.1 加法模型 2.2 加法模型目标函数优化问题 三.前向分步算法流程 3.1 输入 3.2 输出 3.3 流程 更新.更全的< ...
- 编程杂谈——使用emplace_back取代push_back
近日在YouTube视频上看到关于vector中emplace_back与push_back区别的介绍,深感自己在现代C++中还是有不少遗漏的知识点,遂写了段代码,尝试比较两者的差别. 示例代码 #i ...
- Centos7安装及配置DHCP服务
DHCP服务概述: 名称:DHCP - Dynamic Host Configuration Protocol 动态主机配置协议. 功能:DHCP(Dynamic Host Configurati ...
- [Mathematics][MIT 18.02]Detailed discussions about 2-D and 3-D integral and their connections
Since it is just a sort of discussion, I will just give the formula and condition without proving th ...
- 后门木马免杀-msfvenom和msf5(evasion)
贴上使用笔记 不多介绍了 很简单的东西 msfvenom各平台生成木马大全: windows:msfvenom -a x86 --platform Windows -p windows/meterpr ...
- 盘点那些适配Linux的国产常用软件
前几天,10月24日,在这个程序员的节日里,腾讯时隔十一年,更新了QQ for Linux.瞬间,各大技术论坛,群聊,关于Linux的新QQ的话题不断.为什么QQ这么多年不更新QQ for Linux ...
- mysql数据备份之 xtrabackup
上一篇简单介绍了一下mysqldump进行数据库的备份和恢复,这一篇说一下另一种备份工具xtrabackup,在InnoDB事务引擎泛滥的时代,xtrabackup可以很好的支持数据库的热备份,这就很 ...
- 从Go语言编码角度解释实现简易区块链——实现交易
在公链基础上实现区块链交易 区块链的目的,是能够安全可靠的存储交易,比如我们常见的比特币的交易,这里我们会以比特币为例实现区块链上的通用交易.上一节用简单的数据结构完成了区块链的公链,本节在此基础上对 ...