HNOI2018D1T2 转盘

标签: 线段树
132人阅读 评论(0) 收藏 举报
分类:

题意

可以选定一个初始位置,每一个时间可以往后走一步(是一个圆)或者不走,每一个位置有一个出现物品的时间点,如果当前所在位置的物品已经出现则可以将其拿走,求最少要多久可以拿走所有的物品

题解

首先对于一个固定的起点,一定有一种方法使得往下一个点走的次数恰好为n-1
我们可以先任意选择一个最大值Ti,然后我们可以随便选择一个起点,依次处理每一个位置,这样肯定是最优解之一,如果有一个更优的解绕了若干圈,那么我们把在最大值之前选取的一个当前起点的后缀当做新的起点显然和那个最优解答案是相同的,绕回来之后还是继续要走到最大值所在的位置,然后我们选择一个使得答案最小的起点就可以了
具体的,把原式子边长,我们有ans=min(max(T[i+j]+n-j-1)),i=1~n,j>=0
考虑简化式子,设a[i]=t[i]-i
ans=min(i+max(A[j]))+n-1,i=1~n,j>=i
那么我们发现可以把a的一个不上升的单调栈搞出来,设其为S,并且设Si的位置是Wi,那么答案就是min(Wi1+Si)+n1,那么我们需要用线段树来维护这个单调栈
对于每一个位置,我们维护一个fv表示[l,r]其左半部分以及跨越中点的答案的最小值,mi[v]表示整一段的最小值,tree表示整一段a的最大值
然后fv=find(v*2,tree[v*2+1]); find(x,l,r,y)就表示当前这一段值最后加上一个y之后答案的最小值,然后我们直接用一个log来更新fv的值就好了
总复杂度是两个log的

贴代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))

using namespace std;

const int maxn=2e5+5;

int tree[maxn*3],f[maxn*3],mi[maxn*3];
int a[maxn];
int i,j,k,l,m,n,o,x,y,p,an,ans;

void fd(int v,int l,int r,int x){
    if (l==r){
        if (tree[v]>=x) p=l;
    } else{
        int mid=(l+r)/2;
        if (x<tree[v*2+1]) fd(v*2+1,mid+1,r,x); else fd(v*2,l,mid,x);
    }
}
void find(int v,int l,int r,int x){
    if (l==r){
        if (tree[v]<x) an=min(an,l+x);
    } else{
        int mid=(l+r)/2;
        if (x<tree[v*2+1]){
            an=min(an,f[v]);
            find(v*2+1,mid+1,r,x);
        } else find(v*2,l,mid,x);
    }
}
void maketree(int v,int l,int r){
    if (l==r){
        tree[v]=a[l]; mi[v]=a[l]+l;
    } else{
        int mid=(l+r)/2;
        maketree(v*2,l,mid); maketree(v*2+1,mid+1,r);
        an=1e6; find(v*2,l,mid,tree[v*2+1]);
        p=l-1;
        fd(v*2,l,mid,tree[v*2+1]);
        f[v]=min(an,p+1+tree[v*2+1]);
        mi[v]=min(f[v],mi[v*2+1]);
        tree[v]=max(tree[v*2],tree[v*2+1]);
    }
}
void change(int v,int l,int r,int x,int y){
    if (l==r){
        tree[v]=y; mi[v]=y+l;
    } else{
        int mid=(l+r)/2;
        if (x<=mid) change(v*2,l,mid,x,y); else change(v*2+1,mid+1,r,x,y);
        an=1e6; find(v*2,l,mid,tree[v*2+1]);
        p=l-1;
        fd(v*2,l,mid,tree[v*2+1]);
        f[v]=min(an,p+1+tree[v*2+1]);
        mi[v]=min(f[v],mi[v*2+1]);
        tree[v]=max(tree[v*2],tree[v*2+1]);
    }
}
int main(){
    freopen("circle.in","r",stdin);
    freopen("circle.out","w",stdout);
    scanf("%d%d%d",&n,&m,&o);
    fo(i,1,n){
        scanf("%d",&a[i]);
        a[i]=a[i]-i; a[i+n]=a[i]-n;
    }
    maketree(1,1,2*n);
    ans=f[1]+n-1;
    printf("%d\n",ans);
    while (m--){
        scanf("%d%d",&x,&y);
        if (o==1){
            x^=ans; y^=ans;
        }
        y=y-x;
        change(1,1,2*n,x,y);
        change(1,1,2*n,x+n,y-n);
        ans=f[1]+n-1;
        printf("%d\n",ans);
    }
    return 0;
}
查看评论

【BZOJ5286】【HNOI2018】转盘

【题目链接】点击打开链接【思路要点】首先有一个不是非常显然的结论,对于每个询问,一定有一种最优解是从某个点开始先等待一段时间,然后不停顿地走完一圈。关于这个结论的证明我们可以考虑我们现在有一个解的答案...
  • qq_39972971
  • qq_39972971
  • 2018-04-17 18:33:24
  • 67

HNOI2018翻水记

day0 又一次来到了长沙南站。 毕竟不是自己省选所以感觉比较轻松,晚上爽快战斗一下就睡觉了。 day1 看完题后发现好像三题都不是很可做,于是就选择先去刚看起来最清真的t1。 搞来搞去...
  • qq_33229466
  • qq_33229466
  • 2018-04-15 18:50:49
  • 146

HNOI2018 总结

听说可以报名HNOI玩一玩,就去玩了一玩Day0HNOI的流程比较简单,也没有什么报道,就是两天早上考试,下午出成绩,好像讲题都没有。 所以Day0就以找晚餐为由出去走了几个小时Day1由于酒店里考...
  • u011056504
  • u011056504
  • 2018-04-16 11:00:14
  • 219

HNOI2018D1T2 转盘

题意 可以选定一个初始位置,每一个时间可以往后走一步(是一个圆)或者不走,每一个位置有一个出现物品的时间点,如果当前所在位置的物品已经出现则可以将其拿走,求最少要多久可以拿走所有的物品 题解 首...
  • Fate_Zero_Saber
  • Fate_Zero_Saber
  • 2018-04-16 17:10:44
  • 132

【杜教筛】【GDOI2018Day1模拟4.17】呼吸决定

题意 求∑ni=1μ(i)∗im∑i=1nμ(i)∗im\sum_{i=1}^n μ(i)*i^m m&amp;lt;=2e5 n&amp;lt;=1e9 题解 设pi=μ(i)∗im|si...
  • Fate_Zero_Saber
  • Fate_Zero_Saber
  • 2018-04-18 21:48:30
  • 19

最近在做一个抽奖转盘,在这做个小结,好记性不如写博客~~

未经允许,不得转载!! 水平有限,不周之处欢迎指正、交流。 博客原文:http://blog.csdn.net/ime33 现在市面上很多商家为了促进交易,采取各种各样的营销方案,转盘抽...
  • ime33
  • ime33
  • 2017-02-15 16:34:16
  • 3361

游戏转盘html5

div+css+js 只能实现4个扇面 div+css+js简单的4项转盘 html, body { width: 100%;...
  • qq_24734285
  • qq_24734285
  • 2016-11-09 11:07:47
  • 593

【BZOJ1210】【HNOI2004】邮递员

【题目链接】点击打开链接【思路要点】基于连通性的的动态规划模板题。时间复杂度\(O(3^M*N*M)\),实现时需要手写一个小高精。【代码】#include&amp;lt;bits/stdc++.h&...
  • qq_39972971
  • qq_39972971
  • 2018-04-17 18:37:24
  • 14

51nod1588幸运树

题目描述 比得喜欢幸运数字。这里所说的幸运数字是由4和7组成的正整数。比如,数字47,744,4是幸运数字,而5,17,467就不是。 一天,比得遇到一棵由n个点组成的树。另外,这棵树是带权的,即...
  • dcx2001
  • dcx2001
  • 2017-10-18 10:48:09
  • 72

Android开发笔记(九十九)圆形转盘

圆形转盘的实现思想 圆形转盘的运用场景常见的有:抽奖转盘、圆形菜单列表、热点客户端环状列表等等。对于圆形转盘的编码实现,主要难点除了手势的触摸控制之外,就在于旋转角度的计算了。下面是旋转角度计算的解决...
  • aqi00
  • aqi00
  • 2016-05-11 11:08:21
  • 2287
    个人资料
    持之以恒
    等级:
    访问量: 3万+
    积分: 2107
    排名: 2万+
    最新评论