考完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的更多相关文章

  1. 8.7 NOIP模拟测试14 旋转子段+走格子+ 柱状图

    T1 旋转子段 30% 暴力枚举起点和长度,暴力判断,o(n3)  不知道为什么我拿了40分... 60% 每一个点都有一个固定的旋转中心可以转成固定点,枚举旋转点和长度. 100% 用一个vecto ...

  2. 2019.8.7 NOIP模拟测试14 反思总结

    先扔代码 调完自闭网络流了,新一轮考试前看看能不能赶完…… 考得极其爆炸,心态也极其爆炸,真的是认识到自己能力上的不足 思维跑偏,代码能力差 就这样吧,再努力努力,不行就AFO T1旋转子段: 因为我 ...

  3. NOIP模拟测试14「旋转子段·走格子·柱状图」

    旋转子段 连60分都没想,考试一直肝t3,t2,没想到t1最简单 我一直以为t1很难,看了题解发现也就那样 题解 性质1 一个包含a[i]旋转区间值域范围最多为min(a[i],i)----max(a ...

  4. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  5. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  6. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

  7. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

  8. NOIP模拟测试17&18

    NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...

  9. 2019.8.14 NOIP模拟测试21 反思总结

    模拟测试20的还没改完先咕着 各种细节问题=错失190pts T1大约三分钟搞出了式子,迅速码完,T2写了一半的时候怕最后被卡评测滚去交了,然后右端点没有初始化为n…但是这样还有80pts,而我后来还 ...

随机推荐

  1. 【CSS】width和height计算

    width:calc(100% - 20px); width:-webkit-calc(100% - 20px);//chrome width:-moz-calc(100% - 20px);//fir ...

  2. GDB使用总结

    1. GDB概述 GNU发布的调试器,可以查看程序如何运行或崩溃时的状态. 主要功能: 启动程序,可以按照自定义的要求运行程序. 可让被调试的程序在你所指定的断点处停住. 当程序被停住时,可以检查此时 ...

  3. 运维自动化神器ansible之group模块

    ansible之group模块 group模块是用来添加或者删除组 首先使用ansible-doc来查看用法 [root@note0 ansible]# ansible-doc -s group - ...

  4. Mac 10.14 安装抓包工具Fiddler

    环境安装 第一步: 首先,Mac下需要使用.Net编译后的程序,需要用到跨平台的方案Mono(现阶段微软已推出跨平台的方案.Net Core,不过暂时只支持控制台程序).安装程序可以从http://w ...

  5. Linux 命令之 chmod

    命令格式 chmod有以下三种格式 chmod [-cfvR] MODE[,MODE]... FILE... chmod [-cfvR] OCTAL-MODE FILE... chmod [-cfvR ...

  6. 案例——TCP上传图片

    TCP上传图片   继续做一个TCP的相关案例,在客户端上传一张图片到服务端,服务端收到图片后,给客户端回馈上传成功信息. 实现细节: 对于一些文件的读取,若文件偏大,可以始用缓冲区去读取和写入,可以 ...

  7. python自动化测试三部曲之request+django实现接口测试

    国庆期间准备写三篇博客,介绍和总结下接口测试,由于国庆期间带娃,没有按照计划完成,今天才完成第二篇,惭愧惭愧. 这里我第一篇博客的地址:https://www.cnblogs.com/bainianm ...

  8. 算法学习之剑指offer(十一)

    一 题目描述 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推. import java.util.*; ...

  9. js继承机制的实现

    js继承机制的实现 1. 继承的概念 说明继承的最经典的例子:几何形状.实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边).圆是椭圆的一种,它只有一个焦点.三角形.矩形和五边形 ...

  10. [BZOJ1833][ZJOI2010]数字计数

    Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文 ...