zoukankan      html  css  js  c++  java
  • 模拟24 题解

    A. Star Way To Heaven

    如果二分答案,问题就转化为不经过一些等大的圆,能否从左侧到达右侧。

    然后我就不会了。

    其实问题很简单:

    不能从左侧走到右侧,等价于能从下侧沿障碍走到上侧,也就是说一些圆将路阻断开。

    二分答案,用并查集或者dfs都可以做到$O(k^2)$建边之后$O(k)$(不计并查集)验证。

    总复杂度$O(k^2logn)$。

    其实问题就是一个最小瓶颈生成树,prim $O(k^2)$求解。

    B. God Knows

    感觉是dp,然而打不出来,只会打搜索。

    只有颓题解才能维持生活这样子:

    设$dp[i]$表示i以前的点引出的边已经切掉了,选了第i个点引出的边。

    $dp[i]=min limits_{j<i,p[j]<p[i],forall k,j<k<i,p[k]<p[j]或p[k]>p[i]}dp[j]+c[i]$

    转化一下,即

    $mx[j][i]=max limits_{j<k<i,p[k]<p[i]}p[k]$

    $dp[i]=min limits_{j<i,mx[j][i]<p[j]<p[i]}dp[j]+c[i]$

    $mx$的变化可以继承已有信息,于是得到了$O(n^2)$的算法。

    注意:以上纯属意淫出了一个根本无法导向正解的死掉的思路。

    下面是将以上思路转化后的结果:

    根据以上的式子,发现能更新dp[i]的,

    为$dp[j]$,并且要保证j为j~i中p值小于$p[i]$中最大的。

    即,能更新i的是1~i中小于$p[i]$的一段p值单调递减的子序列,要维护的是这段子序列里的dp最小值。

    但是因为受小于$p{i]$限制,难以维护。

    于是接着转换思路,

    因为i与$p[i]$一一对应,将坐标系翻转,于是不再受p[i]限制。

    p[i]随i单调递减,变为i随p[i]单调递减。

    然而仍然无法维护,询问的p[i]是跳跃的。

    线段树维护区间的单调栈,与某个名叫Weed的题异曲同工,

    维护了栈内最小值,左儿子被右儿子更新之后的最小值,右儿子栈底的元素。

    维护时每次延伸出一条链查找答案。

    询问时先找右侧,以得到栈的下一个元素,确定这一次的询问范围。

    注意一些细节就可以了。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define lch (p<<1)
     5 #define rch (p<<1|1)
     6 using namespace std;
     7 const int N=2e5+10;
     8 const int inf=2e9;
     9 int n;
    10 int to[N],w[N];
    11 inline int read(register int x=0,register char ch=getchar(),bool ff=0){
    12     while(!isdigit(ch)) ff=(ch=='-'),ch=getchar();
    13     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    14     return ff?-x:x;
    15 }
    16 struct node{
    17     int l,r,mn,mx,upd_mn;
    18 }s[N<<2];
    19 void build(int p,int l,int r){
    20     s[p].l=l; s[p].r=r;
    21     s[p].mn=s[p].upd_mn=inf;
    22     s[p].mx=-1;
    23     if(l==r) return ;
    24     int mid=l+r>>1;
    25     build(lch,l,mid);
    26     build(rch,mid+1,r);
    27 }
    28 int calc(int p,int nxt){
    29     if(s[p].l==s[p].r) return s[p].mx>nxt?s[p].mn:inf;
    30     if(s[rch].mx>nxt) return min(s[lch].upd_mn,calc(rch,nxt));
    31     return calc(lch,nxt);
    32 }
    33 int nxt;
    34 int query(int p,int l,int r){
    35     if(s[p].l>=l&&s[p].r<=r){
    36         int ans=calc(p,nxt);
    37         nxt=max(s[p].mx,nxt);
    38         return ans;
    39     }
    40     int ans=inf;
    41     if(r>=s[rch].l) ans=min(query(rch,l,r),ans);
    42     if(l<=s[lch].r) ans=min(query(lch,l,r),ans);
    43     return ans;
    44 }
    45 void insert(int p,int pos,int tail,int val){
    46     if(s[p].l==s[p].r){
    47         s[p].mn=val;
    48         s[p].mx=tail;
    49         return ;
    50     }
    51     if(pos<=s[lch].r) insert(lch,pos,tail,val);
    52     else insert(rch,pos,tail,val);
    53     s[p].mx=max(s[lch].mx,s[rch].mx);
    54     s[p].mn=min(s[rch].mn,s[lch].upd_mn=calc(lch,s[rch].mx));
    55 }
    56 int main(){
    57     n=read();
    58     for(int i=1;i<=n;++i) to[i]=read();
    59     for(int i=1;i<=n;++i) w[i]=read();
    60     ++n; to[n]=n; build(1,0,n);
    61     insert(1,0,0,0);
    62     for(int i=1,k;i<=n;++i){
    63         nxt=-1; k=query(1,0,to[i]-1)+w[i];
    64         insert(1,to[i],i,k);
    65         if(i==n) printf("%d
    ",k);
    66     }
    67     return 0;
    68 }
    View Code

    C. Lost My Music

    考场上切掉的简单题。

    然而我的复杂度比正解多一个$log$。

    观察到给出的式子正是斜率的负值,

    于是问题转化为求祖先链上的最大斜率,并将答案设为它的相反数。

    显然用栈维护下凸包即可。

    然而需要考虑的是对于一个节点不止一个儿子,一些信息该怎样继承。

    我用了树上启发式合并的思想,直接更新轻儿子,让重儿子继承栈内的信息,最后将栈清空,走轻儿子。

    单次更新的复杂度为$O(logn)$,每个儿子最多被更新$logn$次,总复杂度为$O(nlog^2n)$。

    正解是使用可持久化链栈,通过倍增弹栈,总复杂度为$O(nlogn)$。

    注意如果暴力弹栈入栈,可能会被长链套菊花的数据卡为$O(n^2)$。

  • 相关阅读:
    css的em是根据什么来写的
    向一个对象数组里面添加新的属性 + 将一个对象数组数据拿出来变成另一个对象
    微信里iphone后退不刷新问题解决方案
    进到页面后input输入框自动获取焦点
    jquery checkbox反复调用attr('checked', true/false)只有第一次生效
    js promise中如何取到[[PromiseValue]]
    js 取得当天0点 / 23:59:59 时间
    jQuery获取包括当前元素的HTML
    C++ 实现 STL 标准库和算法(二)template 编程和迭代器粗解 实验楼笔记
    我现在怎么写博客笔记?
  • 原文地址:https://www.cnblogs.com/skyh/p/11368981.html
Copyright © 2011-2022 走看看