T1 旋转子段

30% 暴力枚举起点和长度,暴力判断,o(n3)  不知道为什么我拿了40分。。。

60% 每一个点都有一个固定的旋转中心可以转成固定点,枚举旋转点和长度。

100% 用一个vector存一下以此点为旋转中心,可以将哪些点转成好点,存区间的左右端点(i,a[i]),将区间长度从小到大排序,枚举中间点,再枚举以他为中心可以将哪些点转成固定点,由于按区间长度排序了,所以第几个点+1就是旋转后当前区间有的固定点个数。区间左右的用前缀和计算即可。

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n,ans,a[],q[];
vector< pair<int,int> >ve[];
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
q[i]=q[i-];
if(a[i]==i) q[i]++;
ve[a[i]+i].push_back(make_pair(max(a[i],i),min(a[i],i)));
}
if(q[n]==n){
printf("%d\n",n);
return ;
}
for(int i=;i<=*n;i++){
sort(ve[i].begin(),ve[i].end());
for(int j=;j<ve[i].size();j++){
int r=ve[i][j].first,l=ve[i][j].second;
ans=max(ans,j++q[l-]+q[n]-q[r]);
}
}
printf("%d\n",ans);
}

旋转子段

T2 走格子

将网格抽象成图,建边,跑dj或spfa。知道建边就好做了,可是我想不到。。。。

需要建的边 一种是空格和空格之间的  一种是穿墙。

第一种直接暴力建就行了。第二种找到离空格最近的墙,到其他墙前的空格的步数为 最近墙+1

最近的墙可以lowerbound二分查找,也可以bfs:从墙往空地扩展,dis[][]中存的就是到最近墙的距离,具体是哪面不重要。

每个空地穿墙后到达的空地,可以o(n×m)扫一遍,他就挨着墙,那么他的位置就是答案,其他的只需要继承前一个的就行。

穿墙到达空地这时需要建单向边,因为从这个空能到这面墙前,这面墙的空地不一定能到达那个空地。因为这个wa了好久,其他的相邻的空地之间是双向边。

主要是要想到将网格之间的可行路建边。

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
struct node
{
int to,nxt,w;
}h[];
int n,m,a[][],ex,ey,sx,sy,tot,nxt[],d[][],lq[][],rq[][],uq[][],dq[][];
int dis[];
char ch[];
queue< pair<int,int> > q;
bool vis[][],v[];
void add(int x,int y,int w)
{
h[++tot].to=y;
h[tot].nxt=nxt[x];
h[tot].w=w;
nxt[x]=tot;
}
int getpos(int x,int y)
{
return (x-)*m+y;
}
void ad(int x,int y,int ds)
{
if(a[x][y]){
if(ds<=d[x][y]){
d[x][y]=ds;
if(!vis[x][y]){
q.push(make_pair(x,y));
vis[x][y]=;
}
}
}
}
void bfs()
{
while(q.size()){
int x=q.front().first,y=q.front().second;
q.pop();vis[x][y]=;
ad(x-,y,d[x][y]+);
ad(x+,y,d[x][y]+);
ad(x,y-,d[x][y]+);
ad(x,y+,d[x][y]+);
}
}
void init()
{
for(int i=n;i>=;i--){
for(int j=m;j>=;j--){
if(a[i][j]){
if(!a[i+][j]) dq[i][j]=getpos(i,j);
else dq[i][j]=dq[i+][j];
if(!a[i][j+]) rq[i][j]=getpos(i,j);
else rq[i][j]=rq[i][j+];
}
}
}
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(a[i][j]){
if(!a[i-][j]) uq[i][j]=getpos(i,j);
else uq[i][j]=uq[i-][j];
if(!a[i][j-]) lq[i][j]=getpos(i,j);
else lq[i][j]=lq[i][j-];
}
}
}
}
void build()
{
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(a[i][j]){
if(a[i-][j]) add(getpos(i,j),getpos(i-,j),);
if(a[i+][j]) add(getpos(i,j),getpos(i+,j),);
if(a[i][j-]) add(getpos(i,j),getpos(i,j-),);
if(a[i][j+]) add(getpos(i,j),getpos(i,j+),);
if(lq[i][j]!=getpos(i,j)) add(getpos(i,j),lq[i][j],d[i][j]);
if(rq[i][j]!=getpos(i,j)) add(getpos(i,j),rq[i][j],d[i][j]);
if(uq[i][j]!=getpos(i,j)) add(getpos(i,j),uq[i][j],d[i][j]);
if(dq[i][j]!=getpos(i,j)) add(getpos(i,j),dq[i][j],d[i][j]);
} }
}
}
void spfa()
{
queue<int> qq;
memset(dis,0x3f,sizeof(dis));
qq.push(getpos(sx,sy));
dis[getpos(sx,sy)]=;
v[getpos(sx,sy)]=;
while(qq.size()){
int x=qq.front();qq.pop();v[x]=;
for(int i=nxt[x];i;i=h[i].nxt){
int y=h[i].to;
if(dis[y]>=dis[x]+h[i].w){
dis[y]=dis[x]+h[i].w;
if(!v[y]){
v[y]=;
qq.push(y);
}
}
}
}
}
int main()
{
memset(d,0x3f,sizeof(d));
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%s",ch+);
for(int j=;j<=m;j++){
if(ch[j]=='.') a[i][j]=;
else if(ch[j]=='C') sx=i,sy=j,a[i][j]=;
else if(ch[j]=='F') ex=i,ey=j,a[i][j]=;
else{
q.push(make_pair(i,j));
vis[i][j]=;
d[i][j]=;
}
}
}
bfs();init();build();spfa();
if(dis[getpos(ex,ey)]>=){
puts("no");
return ;
}
printf("%d\n",dis[getpos(ex,ey)]);
return ;
}

走格子

T3 柱状图此题不可做。。。

首先,以一个点为最高点,那么需要变动的高度是一个单谷的函数,所以三分答案。

我们可以O(n)枚举以谁为最高点,O(logn)三分最高点的高度,O(n)计算答案,总复杂度O(n2logn)。可以得到60分的好成绩。

其实这个思路已经很接近正解了。枚举最高点和三分高度无法优化(skyh的三分答案+退火我不做任何评价,因为我不会),那么就只能对计算答案下手了。

我们确定了最高点(x 枚举)和最高高度(h[x] 三分)那么图形的形状就是确定的了。

设i为x左边的一个点,应该的高度为h[i],原始高度为a[i];

h[i]=h[x]-abs(i-x)  去绝对值得 h[i]-i=h[x]-x 他需要改变的高度Δh=abs(h[i]-a[i])=abs( (h[i]-i)-(a[i]-i) )=abs( (h[x]-x)-(a[i]-i) )

再次分类去绝对值 (h[x]-x)>(a[i]-i) Δh=(h[x]-x)-(a[i]-i)

那么我们设满足i<x&&(h[x]-x)>(a[i]-i) 有cnt个,他们对答案的贡献为cnt×(h[x]-x)-Σ(a[i]-i)

cnt和(a[i]-i)可以用两个树状数组维护:将(a[i]-i)和i当做二元组存起来,按a[i]-i的大小进行排序,得到每个点在数组中的位置。用现在的位置当作树状数组的下标,维护(a[i]-i)的和 和cnt的个数。因为我们是从左往右扫,扫完一个点才会把他对应的值加入树状数组,所以当前树状数组中的值都是满足i<x的。那么我们只需要找到(a[i]-i)<=(h[x]-x)的最后一个位置pos。二分找到这个位置(排序后的数组),他对应的下标就是树状数组中下标的位置。

同理(a[i]-i)>(h[x]-x)的情况 Σ(a[i]-i)-cnt×(h[x]-x) 只需要查询到n的,然后减去pos以前的,剩下的就是我们想要的。

在x右边的也一样,h[i]+i=h[x]+x,其他的一样维护。

这题一共4个树状数组。。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
ll n,ans,mm,a[],idl[],idr[];
pair<ll,ll> l[],r[];
struct node
{
ll c[],cc[];
ll lowbit(ll x)
{
return x&(-x);
}
void add(ll x,ll w,ll num){
while(x<=n){
c[x]+=w;
cc[x]+=num;
x+=lowbit(x);
}
}
pair<ll,ll> query(ll x)
{
pair<ll,ll> as;
while(x){
as.first+=c[x];
as.second+=cc[x];
x-=lowbit(x);
}
return as;
}
}L,R;
ll calc(ll x,ll height)
{
ll res=abs(a[x]-height);
ll pos=upper_bound(l+,l+n+,make_pair(height-x,1ll))-l-;
pair<ll,ll> cost=L.query(pos);
res+=cost.second*(height-x)-cost.first;
pair<ll,ll> cst=L.query(n);
cst.first-=cost.first;cst.second-=cost.second;
res+=cst.first-cst.second*(height-x); pos=upper_bound(r+,r+n+,make_pair(height+x,1ll))-r-;
cost=R.query(pos);
res+=cost.second*(height+x)-cost.first;
cst=R.query(n);
cst.first-=cost.first;cst.second-=cost.second;
res+=cst.first-cst.second*(height+x);
return res;
}
void work()
{
for(ll i=;i<=n;i++) R.add(idr[i],r[idr[i]].first,);
for(ll i=;i<=n;i++){
R.add(idr[i],-r[idr[i]].first,-);
ll lb=max(i,n-i+),rb=mm+n;
while(lb+<rb){
ll mid=(lb+rb)>>;
ll lmid=mid-,rmid=mid;
ll lcost=calc(i,lmid),rcost=calc(i,rmid);
if(lcost>=rcost) lb=mid;
else rb=mid;
}
ans=min(ans,calc(i,lb));
ans=min(ans,calc(i,rb));
L.add(idl[i],l[idl[i]].first,);
}
}
int main()
{
scanf("%lld",&n);ans=0x7ffffffffffffff;
for(ll i=;i<=n;i++){
scanf("%lld",&a[i]);
mm=max(mm,a[i]);
l[i]=make_pair(a[i]-i,i);
r[i]=make_pair(a[i]+i,i);
}
sort(l+,l+n+);
sort(r+,r+n+);
for(ll i=;i<=n;i++){
idl[l[i].second]=i;
idr[r[i].second]=i;
}
work();
printf("%lld\n",ans);
return ;
}

柱状图

改了一下午。。。树状数组的下标理解错了,怎么都不知道是怎么维护的。

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

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

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

  2. NOIP模拟测试14

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

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

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

  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. 诡异问题:tomcat启动一直卡住,strace跟踪提示apache-tomcat核心文件找不到。

    最近遇到了一个诡异的tomcat问题,被这个问题折磨了2天.是这样的,启动tomcat后一直卡在这个点上: org.apache.catalina.core.StandardEngine.startI ...

  2. linux 用du查看硬盘信息

    linux 用du查看硬盘信息 <pre>[root@iZ238qupob7Z web]# df -hFilesystem Size Used Avail Use% Mounted on/ ...

  3. jQuery 源码分析(五) map函数 $.map和$.fn.map函数 详解

    $.map() 函数用于使用指定函数处理数组中的每个元素(或对象的每个属性),并将处理结果封装为新的数组返回,该函数有三个参数,如下: elems Array/Object类型 指定的需要处理的数组或 ...

  4. opencv 图像旋转

    理论 http://www.cnblogs.com/wangguchangqing/p/4045150.html 翻开任意一本图像处理的书,都会讲到图像的几何变换,这里面包括:仿射变换(affine ...

  5. 网格弹簧质点系统模拟(Spring-Mass System by Fast Method)附源码(转载)

    转载:  https://www.cnblogs.com/shushen/p/5311828.html 弹簧质点模型的求解方法包括显式欧拉积分和隐式欧拉积分等方法,其中显式欧拉积分求解快速,但积分步长 ...

  6. Windows中将nginx添加到服务(转)

    下载安装nginx http://nginx.org/en/download.html 下载后解压到C盘 C:\nginx-1.14.0 添加服务 需要借助"Windows Service ...

  7. Android探索之百度地图开发

    目录 前言 地图图层介绍 地图覆盖物介绍 地图事件 POI检索 公交线路查询 线路规划 地理编码 @ 前言 之前自己在做一个小项目时涉及到了百度地图的一些内容,当时因为对百度地图的开发流程不是很了解, ...

  8. Java 打印HelloKitty

    Java第一课 如何在控制台打印出"Hello Kitty" 如图所示,在IDE中使用 System.out.println(); 语句来实现打印 最后附上AIDE下载链接: Ja ...

  9. Flink使用SideOutPut替换Split实现分流

    以前的数据分析项目(版本1.4.2),对从Kafka读取的原始数据流,调用split接口实现分流. 新项目决定使用Flink 1.7.2,使用split接口进行分流的时候,发现接口被标记为deprac ...

  10. 起步:SpringBoot

    pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...