题意:

给出一个 \(k \times k\) 的网格和 \(n\) 次操作。其中 \(k\) 为奇数。

每次操作给出一个数 \(m\)。每次你要找出一个三元组 \((x,l,r)\) 使得:

  1. \(r-l+1=m\)
  2. \((x,l),(x,l+1),(x,l+2),\dots,(x,r)\) 都未被访问过。
  3. \(\sum\limits_{i=l}^r|x-\frac{k+1}{2}|+|y-\frac{k+1}{2}|\) 最小。换句话说,\((x,l),(x,l+1),(x,l+2),\dots,(x,r)\) 到网格正中心的距离之和最小
  4. 在满足 1,2,3 的条件下,若有多个三元组,选择 \(x\) 最小的,若还有多种,选择 \(l\) 最小的。

    求出 \((x,l,r)\) 之后,你会将 \((x,l),(x,l+1),(x,l+2),\dots,(x,r)\) 都设为访问过。

    \(k \in [1,300001]\)。

神仙题 %%%%%(看调试语句就知道我这道题调了多久了)

我们记 \(mid=\frac{k+1}{2}\)

首先有一个显而易见的性质:对于那些没有位置被选择的行,只有最接近 \(mid\) 的两行才会被选。

也就是说,有位置被选择的行一定会组成一个区间。

我们对这两行进行特判。假设目前有位置被选择的行组成的区间为 \((cl,cr)\),那么选择第 \(cl\) 行的最小代价为 \(|mid-cl|\times m+\sum\limits_{i=1}^{\lfloor\frac{m}{2}\rfloor}i+\sum\limits_{i=1}^{\lfloor\frac{m-1}{2}\rfloor}i\),第 \(cr\) 行的代价也同理。

如果我们选择一个有位置被选择的行,那么显然这一行最中心的位置被选择了。

我们将这一行一分为二,分为左右两部分。这里以左半部分为例,右半部分也同理。

假设第 \(i\) 行左半部分最右边的空位为 \(x\),如果 \(x<m\) 就不能选择这一行。

如果 \(x\geq m\),那么可以选择这一行,并且代价最小的区间一定是 \((x-m+1,x)\),考虑如何计算这一行的代价。

我们将这个长度为 \(m\) 的区间的右端点与 \((mid,mid)\) 对齐,此时代价为 \(\frac{m(m-1)}{2}\)。

然后从 \((mid,mid)\) 移动到 \((i,x)\),不难发现每移一步代价增加 \(m\),即 \(m \times (|i-mid|+|x-mid|)+\frac{m(m-1)}{2}\)。

由于 \(m\) 是一个确定的值,代价最小就意味着 \((|i-mid|+|x-mid|)\)。

我们建立一个结构体 \(data\),里面存三个值 \(v,x,l\),并重载小于号使其与上面的比较方式相吻合。

维护一棵线段树,线段树上的节点存该子树中最小的 \(data\)。叶子节点为 \(data\) 的大根堆。

线段树的下标表示 \(x\),也就是第 \(i\) 行左半部分最右侧的空位的位置。

我们要查询 \([m,mid]\) 中最小的三元组,就在 \([m,mid]\) 对应的区间中查找。

如果我们选择一个区间 \((x,l,r)\),就从线段树中删除 \((|mid-x|+|mid-r|,x,r)\) 并加入 \((|mid-x|+|mid-l+1|,x,l-1)\) 即可。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a) a.begin(),a.end()
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,0x3f,sizeof(a))
#define y1 y1010101010101
#define y0 y0101010101010
typedef pair<int,int> pii;
typedef long long ll;
int n,k,mid;
struct data{
ll v;int x,l;
data(ll _v=0,int _x=0,int _l=0){
v=_v;x=_x;l=_l;
}
friend bool operator <(data a,data b){
if(a.v^b.v) return a.v<b.v;
if(a.x^b.x) return a.x<b.x;
return a.l<b.l;
}
friend bool operator >(data a,data b){
return b<a;
}
friend bool operator ==(data a,data b){
return (a.v==b.v&&a.x==b.x&&a.l==b.l);
}
};
const data INF=data(0x3f3f3f3f3f3f3f3fll,0x3f3f3f3f,0x3f3f3f3f);
struct segtree{
struct node{
int l,r;
data mn;
} s[300005<<2];
priority_queue<data,vector<data>,greater<data> > pq[300005];
inline void build(int k,int l,int r){
s[k].l=l;s[k].r=r;s[k].mn=INF;if(l==r) return;
int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
inline void modify(int k,int ind,data p){
// printf("%d\n",k);
// if(!ind) return;
if(s[k].l==s[k].r){
// printf("%d\n",s[k].l);
pq[s[k].l].push(p);
s[k].mn=pq[s[k].l].top();
return;
}
int mid=(s[k].l+s[k].r)>>1;
if(ind<=mid) modify(k<<1,ind,p);
else modify(k<<1|1,ind,p);
s[k].mn=min(s[k<<1].mn,s[k<<1|1].mn);
}
inline void del(int k,int ind){
if(!ind) return;
// printf("%d\n",k);
if(s[k].l==s[k].r){
// printf("%d\n",s[k].l);
// data xx=pq[s[k].l].top();
// printf("delete %d %d %d\n",xx.v,xx.x,xx.l);
// assert(!pq[s[k].l].empty());
pq[s[k].l].pop();
if(pq[s[k].l].empty()) s[k].mn=INF;
else s[k].mn=pq[s[k].l].top();
return;
}
int mid=(s[k].l+s[k].r)>>1;
if(ind<=mid) del(k<<1,ind);
else del(k<<1|1,ind);
s[k].mn=min(s[k<<1].mn,s[k<<1|1].mn);
}
inline data query(int k,int l,int r){
// printf("%d\n",k);
if(l>r) return INF;
if(l<=s[k].l&&s[k].r<=r) return s[k].mn;
int mid=(s[k].l+s[k].r)>>1;
if(r<=mid) return query(k<<1,l,r);
else if(l>mid) return query(k<<1|1,l,r);
else return min(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
}
} L,R;
int main(){
scanf("%d%d",&n,&k);mid=(k+1)>>1;
int cl=mid,cr=mid;L.build(1,0,mid);R.build(1,0,mid);
for(int i=1;i<=n;i++){
int m;scanf("%d",&m);
data ansp=INF;
ll v=1ll*(m/2)*((m/2)+1)/2+1ll*((m-1)/2)*((m-1)/2+1)/2;
if(cl!=0) ansp=min(ansp,data(v+1ll*m*abs(mid-cl),cl,mid-m/2));
if(cr!=k+1) ansp=min(ansp,data(v+1ll*m*abs(mid-cr),cr,mid-m/2));
data x=L.query(1,m,mid),y=R.query(1,m,mid);x.l-=m-1;
// printf("%lld %d %d\n",x.v,x.x,x.l);
// printf("%lld %d %d\n",y.v,y.x,y.l);
if(x.v!=0x3f3f3f3f3f3f3f3fll) x.v=x.v*m+1ll*m*(m-1)/2;
if(y.v!=0x3f3f3f3f3f3f3f3fll) y.v=y.v*m+1ll*m*(m-1)/2;
ansp=min(ansp,x);ansp=min(ansp,y);
if(ansp.v==0x3f3f3f3f3f3f3f3fll){puts("-1");continue;}
// printf("%lld %d %d\n",x.v,x.x,x.l);
// printf("%lld %d %d\n",y.v,y.x,y.l);
printf("%d %d %d\n",ansp.x,ansp.l,ansp.l+m-1);
if(ansp.x==cl){
L.modify(1,ansp.l-1,data(abs(cl-mid)+abs(ansp.l-1-mid),cl,ansp.l-1));
// printf("L %d %d %d %d\n",ansp.l-1,abs(cl-mid)+abs(ansp.l-1-mid),cl,ansp.l-1);
R.modify(1,k-ansp.l-m+1,data(abs(cl-mid)+abs(ansp.l+m-mid),cl,ansp.l+m));
// printf("R %d %d %d %d\n",k-ansp.l-m+1,abs(cl-mid)+abs(ansp.l+m-mid),cl,ansp.l+m);
if(cl==cr) cr++;cl--;
continue;
}
else if(ansp.x==cr){
L.modify(1,ansp.l-1,data(abs(cr-mid)+abs(ansp.l-1-mid),cr,ansp.l-1));
// printf("L %d %d %d %d\n",ansp.l-1,abs(cr-mid)+abs(ansp.l-1-mid),cr,ansp.l-1);
R.modify(1,k-ansp.l-m+1,data(abs(cr-mid)+abs(ansp.l+m-mid),cr,ansp.l+m));
// printf("R %d %d %d %d\n",k-ansp.l-m+1,abs(cr-mid)+abs(ansp.l+m-mid),cr,ansp.l+m);
cr++;
continue;
// continue;
}
else if(ansp==x){
L.del(1,ansp.l+m-1);
// printf("delL %d\n",ansp.l+m-1);
L.modify(1,ansp.l-1,data(abs(ansp.x-mid)+abs(ansp.l-1-mid),ansp.x,ansp.l-1));
// printf("L %d %d %d %d\n",ansp.l-1,abs(ansp.x-mid)+abs(ansp.l-1-mid),ansp.x,ansp.l-1);
// continue;
}
else if(ansp==y){
R.del(1,k-ansp.l+1);
// printf("delR %d\n",k-ansp.l+1);
R.modify(1,k-(ansp.l+m)+1,data(abs(ansp.x-mid)+abs(ansp.l+m-mid),ansp.x,ansp.l+m));
// printf("R %d %d %d %d\n",k-(ansp.l+m)+1,abs(ansp.x-mid)+abs(ansp.l+m-mid),ansp.x,ansp.l+m);
// continue;
}
}
return 0;
}

【2020五校联考NOIP #6】最佳观影的更多相关文章

  1. 【2020五校联考NOIP #6】三格缩进

    题意: 给出 \(n\) 个数 \(a_1,a_2,\dots,a_n\),你要进行 \(m\) 次操作,每次操作有两种类型: \(1\ p\ x\):将 \(a_p\) 改为 \(x\). \(2\ ...

  2. 【2020五校联考NOIP #8】自闭

    题目传送门 题意: 有一个 \(n \times m\) 的矩阵,里面已经填好了 \(k\) 个非负整数. 问是否能在其它 \(n \times m-k\) 个格子里各填上一个非负整数,使得得到的矩阵 ...

  3. 【2020五校联考NOIP #8】狗

    题面传送门 原题题号:Codeforces 883D 题意: 有 \(n\) 个位置,每个位置上要么有一条狗,要么有一根骨头,要么啥都没有. 现在你要给每个狗指定一个方向(朝左或朝右). 朝左的狗可以 ...

  4. 【2020五校联考NOIP #7】道路扩建

    题面传送门 题意: 给出一张 \(n\) 个点 \(m\) 条边的无向图 \(G\),第 \(i\) 条边连接 \(u_i,v_i\) 两个点,权值为 \(w_i\). 你可以进行以下操作一次: 选择 ...

  5. 【2020五校联考NOIP #4】今天的你依旧闪耀

    题面传送门 题意: 对于一个长度为 \(n\)(\(n\) 为偶数)的排列 \(p\),定义一次"变换"后得到的排列 \(p'\) 为: \(p'_i=\begin{cases}p ...

  6. 【2020五校联考NOIP #3】序列

    题面传送门 原题题号:Codeforces Gym 101821B 题意: 给出一个排列 \(p\),要你找出一个最长上升子序列(LIS)和一个最长下降子序列(LDS),满足它们没有公共元素.或告知无 ...

  7. 【2020五校联考NOIP #7】伟大的卫国战争

    题面传送门 题意: 数轴上有 \(n\) 个点,现在要在它们之间连 \(m\) 条边,第 \(i\) 条边连接 \(a_i,b_i\) 两个点. 现在你要钦定每条边连在数轴的上方还是下方,使得任意两条 ...

  8. 【2020五校联考NOIP #2】矩阵

    咕咕咕到现在~ 题面传送门 题意: 给出一个 \(n\times n\) 的矩阵 \(A\).要你求有多少个 \(n\times n\) 的矩阵 \(B\) 满足: 每一行都是 \(1\) 到 \(n ...

  9. 【五校联考1day2】JZOJ2020年8月12日提高组T2 我想大声告诉你

    [五校联考1day2]JZOJ2020年8月12日提高组T2 我想大声告诉你 题目 Description 因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一 ...

随机推荐

  1. django 1.11.16之环境搭建

    django版本:django1.11.16  windows环境 python 3.6.3    !!!可先安装虚拟环境在进行环境搭建  1.安装django:pip install django= ...

  2. 个人记录:对于python学习的反思和总结(一)

    在写代码时,总是遇到写着写着不知道怎么写了的情况,或者无法把自己的想法用程序表达出来,所以有时候我们需要建立一个自己的编程思路,对一个具体程序的编程有一个比较清晰的想法:因此我把自己的思路总结了一下, ...

  3. 初始HTML04

    HTML 列表标签 无序列表 默认用实心圆点标识列表项 1 <ul> 2 <li>list item 列表项</li> 3 <li>list item ...

  4. 小白自制Linux开发板 八. Linux音频驱动配置

    不知不觉小白自制开发板系列已经到第八篇了,本篇要配置的是音频驱动,也算是硬件部分的最后一片了,积攒的文章也差不多全放完了,后续更新可能会放缓,还请见谅. 对于F1C200s是自带了多媒体处理功能的,所 ...

  5. 【c++ Prime 学习笔记】第4章 表达式

    表达式由一个或多个运算对象组成,对表达式求值返回结果. 字面值和变量是最简单的表达式 把运算符和运算对象组合可得到复杂表达式. 4.1 基础 4.1.1 基本概念 一元运算符作用于一个对象,如取地址符 ...

  6. 使用json-path解析json

    在我们的日常开发中,有时候需要从一个json字符串中获取一个值,或者从一段json字符串中获取到某些值,如果先使用Gson或Jackson转换成java对象在获取值,有些时候是很麻烦的,那么有没有一种 ...

  7. java线程同步以及对象锁和类锁解析(多线程synchronized关键字)

    一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...

  8. H3C 三层交换基于IP限速

    一.背景 目前百度爬虫爬取业务总是按照自己的性能进行抓取客户数据,从来不考虑客户端的网络承受能力,导致客户端网络带宽超出预算范围,因此在客户端方面针对百度的无限制抓取采取相应的策略. 二.解决方案: ...

  9. Netfilter和iptables介绍

    前言 在开始Kubernetes的网络之前我们先来学习Netfilter,Netfilter可能了解的人比较少,但是iptables用过 Linux的都应该知道.本文主要介绍Netfilter与ipt ...

  10. Cobar SQL审计的设计与实现

    背景介绍 Cobar简介 Cobar 是阿里开源的一款数据库中间件产品. 在业务高速增长的情况下,数据库往往成为整个业务系统的瓶颈,数据库中间件的出现就是为了解决数据库瓶颈而产生的一种中间层产品. 在 ...