旋转子段

连60分都没想,考试一直肝t3,t2,没想到t1最简单

我一直以为t1很难,看了题解发现也就那样

题解

性质1

一个包含a[i]旋转区间值域范围最多为min(a[i],i)----max(a[i],i)

感性理解

举个例子,例如3 7 1 4 5 6 2

这个子段包含a[2]的最大为值域范围2----7

具体证明我不会

性质2

翻转后满足固定点对的点满足

a[i]+i==a[j]+j

证明

因为翻转之前a[i]==j&&a[j]==i才满足翻转之后都构成点对

移项得到a[i]+i==a[j]+j

有了这两条性质我们可以得到一个$n^2$算法

for(ll i=1;i<=n;i++){
tot=0;
for(ll j=min(i,a[i]);j<=max(i,a[i]);j++)
if(a[j]+j==a[i]+i)
tot++;
}

得到tot最大值输出即可

70分代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1010101
ll f[A],a[A],sum[A];
ll n,ans=-1,tot=0;
vector<ll>too[501010];
int main(){
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1];
if(a[i]==i) sum[i]++;
}
for(ll i=1;i<=n;i++){
tot=0;
for(ll j=min(i,a[i]);j<=max(i,a[i]);j++){
if(a[j]+j==a[i]+i){
tot++;
}
}
// printf("n=%lld max=%lld min=%lld i=%lld tot=%lld\n",n,max(i,a[i]),min(i,a[i]),i,tot);
ans=max(tot+sum[n]-sum[max(i,a[i])]+sum[min(i,a[i])-1],ans);
}
printf("%lld\n",ans);
}

100分

莫队维护一下询问,需要卡常,卡常到自闭,fh卡常大师

分块0.53最优

#include<bits/stdc++.h>
using namespace std;
#define ll int
const int A=1010101,L=1<<20|1;
#define getchar() ((S==T&&(T=(S=buf)+fread(buf,1,L,stdin),S==T))?EOF:*S++)
ll f[A],a[A],sum[A],tong[A],belong[A];
ll n,ans=-1,l=1,r=0,ou=0,block;
char buf[L],*S,*T;
struct moo{
ll zhong,r,l,a;
friend bool operator < (moo a,moo b){
return ((belong[a.l]^belong[b.l]))?a.l<b.l:((belong[a.l]&1)?a.r<b.r:a.r>b.r);
}
}mo[A];
inline ll read(){
ll x=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
int main(){
n=read();
block=pow(n,0.53);
for(register ll i=1;i<=n;i++){
a[i]=read();
sum[i]=sum[i-1];
if(!(a[i]^i)) sum[i]++;
belong[i]=(i-1)/block+1;
}
for(register ll i=1;i<=n;i++){
mo[i].zhong=i;
mo[i].r=max(i,a[i]);
mo[i].l=min(i,a[i]);
mo[i].a=a[i];
}
sort(mo+1,mo+n+1);
for(register ll i=1;i<=n;i++){
while(l>mo[i].l) tong[l-1+a[l-1]]++,l--;
while(l<mo[i].l) tong[l+a[l]]--,l++;
while(r>mo[i].r) tong[r+a[r]]--,r--;
while(r<mo[i].r) tong[r+1+a[r+1]]++,r++;
ans=max(tong[mo[i].zhong+mo[i].a]+sum[n]-sum[mo[i].r]+sum[mo[i].l-1],ans);
}
printf("%d",ans);
}

走格子

显然贪心有门走门不对一个稍简单的数据就可以卡掉你

7 8
########
##.F#..#
#...C..#
##..#..#
##.....#
#..#...#
########

那怎么办,只能走八个方向爆搜吗?

显然可以最短路!

从每个墙开始搜直接得到每个点到墙最短距离,然后每两相邻点之间建边,点墙之间建边

例如               (墙)

       |

      50

      |

(墙)-----21------Q-------------500000000-------(墙)

      |

      |

      600

      |

      (墙)

我们只需要将Q与四个墙方向边权都设置为21即可.(例如可以在2打传送门  然后在4打传送门从2传送到4,那么所有最小代价都为21)

很简单对不对,直接跑最短路就行了

保证最短路会松弛掉一些不可行解

例如

      (墙)

        |

       50

     (墙)|

(墙)------21--Q-------500000--(墙)

      |

      50

      |

     (终点)

向上走一步再打传送门会松弛掉21这条边

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 5010101
#define py printf("toot\n")
#define fr first
#define se second
#define mp(x,y) make_pair(x,y)
ll zh[610][610],top[610][610],low[610][610],zuo[610][610],you[610][610],bs[610][610],head[A],nxt[A],ver[A],edg[A],dis[A];
const ll nowx[5]={0,0,0,1,-1};
const ll nowy[5]={0,1,-1,0,0};
bool vis[A];
ll n,m,zhongx,zhongy,qix,qiy,ttt=0,tot=0;
deque<pair<ll,ll> >q,toot;
char s[610][610];
ll id(ll i,ll j){
return (i-1)*m+j;
}
void add(ll x,ll y,ll z){
nxt[++tot]=head[x],head[x]=tot,ver[tot]=y,edg[tot]=z;return ;
}
void ins(ll x,ll y,ll d){
if(!bs[x][y]&&s[x][y]=='.'){
bs[x][y]=d;
q.push_back(mp(x,y));
}
}
void bfs(){
while(!q.empty()){
ll kx=q.front().fr,ky=q.front().se;
q.pop_front();
// py;
for(ll i=1;i<=4;i++){
ins(kx+nowx[i],ky+nowy[i],bs[kx][ky]+1);
}
}
}
void init(){
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++){
if(s[i][j]=='#') continue;
if(s[i][j-1]=='#') zuo[i][j]=id(i,j);
else zuo[i][j]=zuo[i][j-1];
if(s[i-1][j]=='#') top[i][j]=id(i,j);
else top[i][j]=top[i-1][j];
}
for(ll i=n;i>=1;i--)
for(ll j=m;j>=1;j--){
if(s[i][j]=='#') continue;
if(s[i][j+1]=='#') you[i][j]=id(i,j);
else you[i][j]=you[i][j+1];
if(s[i+1][j]=='#') low[i][j]=id(i,j);
else low[i][j]=low[i+1][j];
}
}
void addb(){
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++){
if(s[i][j]=='#') continue;
ll d=id(i,j);
if(s[i+1][j]=='.') add(d,id(i+1,j),1),add(id(i+1,j),d,1);
if(s[i][j+1]=='.') add(d,id(i,j+1),1),add(id(i,j+1),d,1);
if(zuo[i][j]!=d)add(d,zuo[i][j],bs[i][j]);
if(you[i][j]!=d)add(d,you[i][j],bs[i][j]);
if(top[i][j]!=d)add(d,top[i][j],bs[i][j]);
if(low[i][j]!=d)add(d,low[i][j],bs[i][j]);
}
}
void spfa(ll o){
vis[o]=1;
memset(dis,0x7f,sizeof(dis));
dis[o]=0;
deque<ll> toot;
toot.push_back(o);
while(!toot.empty()){ ll x=toot.front();
toot.pop_front();
for(ll i=head[x];i;i=nxt[i]){
ll y=ver[i];
if(dis[y]>dis[x]+edg[i]){
dis[y]=dis[x]+edg[i];
if(!vis[y]){
vis[y]=1;
toot.push_back(y);
}
}
}
vis[x]=0;
}
}
int main(){
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++){
scanf("%s",s[i]+1);
for(ll j=1;j<=m;j++){
if(s[i][j]=='#'){
q.push_back(mp(i,j));
}
else
if(s[i][j]=='C'){
s[i][j]='.';
qix=i;
qiy=j;
}
if(s[i][j]=='F'){
s[i][j]='.';
zhongx=i;
zhongy=j;
}
}
}
bfs(),init(),addb(),spfa(id(qix,qiy));
if(dis[id(zhongx,zhongy)]>=1202134)
printf("no\n");
else
printf("%lld\n",dis[id(zhongx,zhongy)]);
}

柱状图

模拟退火板子题,非常板子

模拟退火最吼了

即使是板子我也要说说

首先关于

    nth_element(s+1,s+mid,s+n+1);

为什么要求出中位数,

前置知识

坐标轴上有很多点,点与点之间有一个距离,你将所有点移到同一个点最小花费

显然是移到中位数的点

那么应用到这个题呢?

你可以将题目要求转化,首先全部移到同一水平线上,然后再加出值

比它高的降低,比它矮的升高,换成坐标轴我们就用到了中位数

然后

if(tmpans<nowans||exp(-D/T)*RAND_MAX>rand())

为什么是

exp(-D/T)*RAND_MAX>rand()

不是

exp(D/T)*RAND_MAX>rand()

问的好啊!

首先我们如果当前解优那么你会通过tmpans<nowans跳过

然后如果当前解不优D一定是负的,如果D为负的那么D越小-D越大.D小代表当前解非常差,让它变成其他解概率更大

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1010101
const double eps=1e-5;
const double delta=0.98;
const double fj=1;
ll n,ans=0x7ffffffffffffff;
ll s[A],h[A];
ll check(ll pos){
for(ll j=1;j<=n;j++)
s[j]=h[j]+abs(pos-j);
ll mid=n+1>>1;
nth_element(s+1,s+mid,s+n+1);
ll val=s[mid];ll tot=0;
if(val<max(pos,n-pos+1))
val=max(pos,n-pos+1);
for(ll i=1;i<=n;i++)
tot+=abs(s[i]-val);
return tot;
}
int main(){
srand(time(0));
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
scanf("%lld",&h[i]);
}
double T=1000;
ll now=(n+1)>>1;
ll nowans=check(now);
while(T>eps){
ll tmp=now+(2ll*rand()-RAND_MAX)*T*0.000001;
tmp=(tmp%n+n-1)%n+1;
ll tmpans=check(tmp),D=tmpans-nowans;
if(tmpans<nowans||exp(-D/T)*RAND_MAX>rand())
nowans=tmpans,now=tmp;
if(tmpans<ans) ans=tmpans;
T*=delta;
}
printf("%lld\n",ans);
}

NOIP模拟测试14「旋转子段·走格子·柱状图」的更多相关文章

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

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

  2. NOIP模拟测试17「入阵曲&#183;将军令&#183;星空」

    入阵曲 题解 应用了一种美妙移项思想, 我们先考虑在一维上的做法 维护前缀和$(sum[r]-sum[l-1])\%k==0$可以转化为 $sum[r]\% k==sum[l-1]\%k$开个桶维护一 ...

  3. NOIP模拟测试11「string&#183;matrix&#183;big」

    打的big出了点小问题,maxx初值我设的0然后少了10分 第二题暴力打炸 第一题剪了一些没用的枝依然40分 总分70 这是一次失败的考试 string 想到和序列那个题很像,但我没做序列,考场回忆学 ...

  4. NOIP模拟测试5「星际旅行·砍树·超级树」

    星际旅行 0分 瞬间爆炸. 考试的时候觉得这个题怎么这么难, 打个dp,可以被儿子贡献,可以被父亲贡献,还有自环,叶子节点连边可以贡献,非叶子也可以贡献,自环可以跑一回,自环可以跑两回, 关键是同一子 ...

  5. NOIP模拟测试14

    考完19了再写14,我也是够咕的. 14的题很好,也充分暴露了我的问题. T1是个分析性质推结论的题 对于区间[L,R],不妨设a[L]!=a[R],那么两个端点对答案没有贡献,也就是[L+1,R], ...

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

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

  7. NOIP模拟测试19「count·dinner·chess」

    反思: 我考得最炸的一次 怎么说呢?简单的两个题0分,稍难(我还不敢说难,肯定又有人喷我)42分 前10分钟看T1,不会,觉得不可做,完全不可做,把它跳了 最后10分钟看T1,发现一个有点用的性质,仍 ...

  8. NOIP模拟测试18「引子·可爱宝贝精灵·相互再归的鹅妈妈」

    待补 引子 题解 大模拟,注意细节 代码1 #include<bits/stdc++.h> using namespace std; int n,m;char a[1005][1005]; ...

  9. NOIP模拟测试15「建造城市city(插板法)·轰炸·石头剪刀布」

    建造城市 题解 先思考一个简单问题 10个$toot$ 放进5间房屋,每个房屋至少有1个$toot$,方案数 思考:插板法,$10$个$toot$有$9$个缝隙,$5$间房屋转化为$4$个挡板,放在t ...

随机推荐

  1. windows 7系统封装总结

    win7系统封装总结 需求:对于个人家庭用户,网上下载原版镜像或者下载好别人封装好的系统都无所谓,但是在公司办公的特殊环境下, 有时需要经常装一些特殊的软件,根据实际情况,封装一个适合本公司使用环境的 ...

  2. JavaI/O流汇总

    Java中常见流学习汇总 流的含义 流在Java中是指计算中流动的缓冲区. 从外部设备流向中央处理器的数据流成为"输入流",反之成为"输出流". 字符流和字节流 ...

  3. Java并发-线程池篇-附场景分析

    作者:汤圆 个人博客:javalover.cc 前言 前面我们在创建线程时,都是直接new Thread(): 这样短期来看是没有问题的,但是一旦业务量增长,线程数过多,就有可能导致内存异常OOM,C ...

  4. 四种方式带你层层递进解剖算法---hash表不一定适合寻找重复数据

    一.题目描述 找出数组中重复的数字 > 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次. ...

  5. SpringBoot中获取上下文

    在实际开发中,有时候会根据某个bean的名称或class到Spring容器中获取对应的Bean.这里只做个简单的记录,方便后续自查. @Component public class SpringCon ...

  6. java的"\\s+"什么意思?

    例如:String[] tt=addr.split("\\s+");\\s ==\s 表示转义字符 ,\s表示匹配任意空格(包括空格,制表符,换页符)\\s+中的'+'表示多次匹配

  7. Kubernetes 部署微服务电商平台(16)

    一.概念 微服务就是很小的服务,小到一个服务只对应一个单一的功能,只做一件事.这个服务可以单独部署运行,服务之间可以通过RPC来相互交互,每个微服务都是由独立的小团队开发,测试,部署,上线,负责它的整 ...

  8. nosql数据库之Redis概念及基本操作

    一.概述 redis是一种nosql数据库(非关系型数据库),他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(st ...

  9. .NET6系列:微软正式宣布Visual Studio 2022

    系列目录     [已更新最新开发文章,点击查看详细] 首先,我们要感谢正在阅读这篇文章的你,我们所有的产品开发都始于你也止于你,无论你是在开发者社区上发帖,还是填写了调查问卷,还是向我们发送了反馈意 ...

  10. String、Stringbuilder、StringBuffer异同

    相同点: String.Stringbuilder.StringBuffer 都可以操作字符串 String 是被final修饰的,容量定长 Stringbuilder 和 Stringbuilder ...