bzoj1007: [HNOI2008]水平可见直线(单调栈)

4人阅读 评论(1) 收藏 举报
分类:

题目传送门
做完这题推荐3190。升级版

解法:
单调栈维护下凸包
先按直线的k来排序
当前直线为i,栈顶为x,栈顶下一个为y。
如果i和x的交点在x和y的交点的左边的话。
那么x是看不到的。踢掉。

最后剩下的就是答案。

代码实现:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node {int c,lc,rc;ll s;}t[2000010];int cnt,rt[110000];
void build(int &u,int l,int r,int p,int s) {
    if(u==0)u=++cnt;t[u].c++;t[u].s+=(ll)s;
    if(l==r)return ;int mid=(l+r)/2;
    if(p<=mid)build(t[u].lc,l,mid,p,s);
    else build(t[u].rc,mid+1,r,p,s);
}
void Merge(int &u1,int u2) {
    if(u1==0) {u1=u2;return ;}if(u2==0)return ;
    t[u1].c+=t[u2].c;t[u1].s+=t[u2].s;
    Merge(t[u1].lc,t[u2].lc);Merge(t[u1].rc,t[u2].rc);
}
int find_mid(int &u1,int &u2,int l,int r,int k) {
    if(l==r)return l;int mid=(l+r)/2;
    int c=t[t[u1].lc].c-t[t[u2].lc].c;
    if(k<=c)return find_mid(t[u1].lc,t[u2].lc,l,mid,k);
    else return find_mid(t[u1].rc,t[u2].rc,mid+1,r,k-c);
}
int find_lc(int &u1,int &u2,int l,int r,int p) {
    if(t[u1].c-t[u2].c==0)return 0;
    if(l==r) return t[u1].c-t[u2].c;int mid=(l+r)/2;
    if(p<=mid)return find_lc(t[u1].lc,t[u2].lc,l,mid,p);
    else return find_lc(t[u1].rc,t[u2].rc,mid+1,r,p)+t[t[u1].lc].c-t[t[u2].lc].c;
}
ll find_ls(int &u1,int &u2,int l,int r,int p) {
    if(t[u1].s-t[u2].s==0) return 0;
    if(l==r)return t[u1].s-t[u2].s;int mid=(l+r)/2;
    if(p<=mid)return find_ls(t[u1].lc,t[u2].lc,l,mid,p);
    else return find_ls(t[u1].rc,t[u2].rc,mid+1,r,p)+t[t[u1].lc].s-t[t[u2].lc].s;
}
struct edge {int x,id;}a[110000];ll s[110000];
bool cmp(edge n1,edge n2){return n1.x<n2.x;}
bool cmp1(edge n1,edge n2){return n1.id<n2.id;}
int main() {
    //freopen("akc.in","r",stdin);freopen("akc.out","w",stdout);
    int n,k;scanf("%d%d",&n,&k);int mmax=0;
    for(int i=1;i<=n;i++) {scanf("%d",&a[i].x);a[i].id=i;}
    if(k==1){printf("0\n");return 0;}
    sort(a+1,a+1+n,cmp);int tot=0;a[0].x=-1;int tt=0;
    for(int i=1;i<=n;i++) if(a[i].x!=a[i-1].x)tt++;
    for(int i=1;i<=n;i++) {if(a[i].x!=a[i-1].x)tot++;build(rt[a[i].id],1,tt,tot,a[i].x);s[tot]=a[i].x;}
    for(int i=1;i<=n;i++) Merge(rt[i],rt[i-1]);
    sort(a+1,a+1+n,cmp1);ll T=0;for(int i=1;i<k;i++)T+=ll(a[i].x);ll Ans=ll(100000000000);a[0].x=0;
    for(int i=k;i<=n;i++) {
        T+=ll(a[i].x);T-=ll(a[i-k].x);
        int p=find_mid(rt[i],rt[i-k],1,tt,(k+1)/2);
        int lc=find_lc(rt[i],rt[i-k],1,tt,p),rc=k-lc;
        ll ls=find_ls(rt[i],rt[i-k],1,tt,p),rs=T-ls;
        Ans=min(Ans,ll(lc*s[p])-ls+rs-ll(rc*s[p]));
    }printf("%lld\n",Ans);
    return 0;
}
查看评论

【bzoj1007】[HNOI2008]水平可见直线 单调栈

Description在xoy直角坐标平面上有n条直线L1,L2,…Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的. 例如,对于直线: ...
  • LOI_DQS
  • LOI_DQS
  • 2015-10-23 17:29:50
  • 1469

【计算几何】[HNOI2008][HYSBZ/BZOJ1007]水平可见直线

题目链接分析如果两条直线斜率相等,显然,截距较小的那一条无论如何都不可见,删掉它们。 我们可以将剩下直线按照斜率的数值从小到大排序。 假设第i条直线是可见的,然后,我们从第i+1条开始向后枚举,分...
  • outer_form
  • outer_form
  • 2016-02-02 14:08:26
  • 938

[HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB Description Input 第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi Output...
  • JokerPoker
  • JokerPoker
  • 2014-12-29 08:20:24
  • 454

[单调栈] bzoj1007: [HNOI2008]水平可见直线

1007: [HNOI2008]水平可见直线:http://www.lydsy.com/JudgeOnline/problem.php?id=1007 因为有解析式所以很好算啊 不难发现能看到的直...
  • qq_36038511
  • qq_36038511
  • 2018-03-01 19:31:36
  • 12

[BZOJ1007][HNOI2008]水平可见直线(单调栈+计算几何)

无论如何困难,不可求人怜悯。
  • Clove_unique
  • Clove_unique
  • 2016-05-11 23:00:14
  • 452

[bzoj1007][HNOI2008]水平可见直线 单调栈

单调栈
  • youhavepeople
  • youhavepeople
  • 2017-08-07 15:33:37
  • 113

【单调栈】BZOJ1007 [HNOI2008]水平可见直线

题面在这里A水题ing……多画几个例子,就会发现,其实要我们维护一个类似下凸壳的东西 果断对斜率由小到大排序然后就会发现,对于3条直线i,j,ki,j,k满足ki...
  • linkfqy
  • linkfqy
  • 2017-07-11 13:37:05
  • 433

[BZOJ1007][HNOI2008]水平可见直线(单调栈)

ATP思考这一篇题解的摘要该写什么已经思考了很久了,最后只好像这样胡乱写一点了事了。。因为今天发的题解太多了有趣的事情都说完了。。。。...
  • FromATP
  • FromATP
  • 2016-11-12 19:07:23
  • 210

[bzoj1007]:[HNOI2008]水平可见直线(单调栈)

传送门 姑且算是计算几何第一题吧。。 首先,最后的图形一定是一个凸包形状的东西。 所以,我们按照k递增为第一关键字,b递减为第二关键字,排个序。 然后我们就可以维护一个单调栈,处理结果了。 ...
  • stone41123
  • stone41123
  • 2017-11-22 19:06:22
  • 73

[bzoj1007][HNOI2008]水平可见直线(单调栈+几何)

国庆七天学Day1
  • Blue_CuSO4
  • Blue_CuSO4
  • 2017-10-01 10:44:35
  • 98
    个人资料
    持之以恒
    等级:
    访问量: 1万+
    积分: 2350
    排名: 1万+
    博客专栏
    最新评论