zoukankan      html  css  js  c++  java
  • [HNOI/AHOI2018]转盘


    题解

    问题是一个环不方便处理所以我们可以把ta倍长成链
    首先可以发现这个东西可以看做是先在初始节点停留若干分钟再花(n-1)分钟畅通的走完(n)个点
    那么从第(i)个点开始走第(n+i-1)个点这一圈花费的时间就是(st[i]=max(sum_{j=i}^{n+i-1}T_j+i-j)+n-1)
    (A_i=T_i-i)
    那么(st[i]=max(sum_{j=i}^{n+i-1}A_j+i)+n-1)
    其实不需要过多的考虑边界问题,因为(A_j+i)一定不小于(A_{n+j}+i)
    所以(st[i]=max(sum_{j=i}^{n imes 2}A_j+i)+n-1)
    那么这样就可以用线段树维护了
    需要维护一个(A_i)的最大值和(st_i)的最小值即可
    但是每次修改(A)都可能会影响一段区间的(st)
    所以(pushup)的时候会比较麻烦,需要考虑右儿子对左儿子的影响
    线段树的相关实现具体看代码

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 200005 ;
    using namespace std ;
    
    inline int read() {
        char c = getchar() ; int x = 0 , w = 1 ;
        while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
        while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
        return x*w ;
    }
    
    int n , m , op , lstans ;
    int p[M] , tmx[M * 4] , ans[M * 4] ;
    /*
    tmx[i] 为区间的 T[i] - i 的最大值
    ans[i] 为区间的 min( max(T[j] - j) + i ) 
    
    */
    
    # define ls (now << 1)
    # define rs (now << 1 | 1)
    int query(int l , int r , int k , int now) { // k为要来取得左边区间答案的tmx值 
        if(l == r) return l + max( tmx[now] , k ) ;
        int mid = (l + r) >> 1 ;
        if( tmx[rs] >= k ) return min( ans[now] , query(mid + 1 , r , k , rs) ) ; // 显然一个点的左儿子所对应的tmx值应该是比右儿子要大的,所以如果右儿子也比ta大,那么就只能继续去递归右子树看看能不能找到比ta小的 ,最终是要返回答案的最小值,所以还要和当前节点的答案取min 
        else return min( k + mid + 1 , query(l , mid , k , ls) ) ; // 如果右儿子的tmx比ta小,那么ta就可以来取得左边的区间的答案,所以直接递归左子树,并且与右子树的最小答案(k+mid+1:因为右子树的最大值小于ta,所以整个右子树的答案都是ta+pos,而mid+1是最小的pos)取min 
    }
    inline void pushup(int l , int mid , int now) {
        tmx[now] = max( tmx[ls] , tmx[rs] ) ; // tmx更新比较简单 
        ans[now] = query(l , mid , tmx[rs] , ls) ;
    /*  由于我们倍长了整个T,所以只需要考虑左区间当开头的情况即可 
    	如果也把右区间的答案计入的话,整棵线段树的右半边的更新长度都不到n,更新信息错误 
    	所以只需要考虑右边的区间对左边区间的影响即可 
    */
    }
    void build(int l , int r , int now) {
        if(l == r) {
            tmx[now] = p[l] - l ; 
            ans[now] = p[l] ;
            return ;
        }
        int mid = (l + r) >> 1 ;
        build(l , mid , ls) ; 
    	build(mid + 1 , r , rs) ;
        pushup(l , mid , now) ;
    }
    void change(int x , int l , int r , int now) {
        if(l == r) {
            tmx[now] = p[l] - l ; 
            ans[now] = p[l] ;
            return ;
        }
        int mid = (l + r) >> 1 ;
        if(mid >= x) change(x , l , mid , ls) ;
        else change(x , mid + 1 , r , rs) ;
        pushup(l , mid , now) ;
    }
    int main() {
        n = read() ; m = read() ; op = read() ;
        for(int i = 1 ; i <= n ; i ++) p[i] = p[n + i] = read() ;
        build(1 , n * 2 , 1) ; lstans = ans[1] + n - 1 ;
        printf("%d
    ",lstans) ; int x , y ;
        while(m --) {
            x = read() ^ (op * lstans) ; y = read() ^ (op * lstans) ;
            p[x] = p[n + x] = y ;
            change(x , 1 , n * 2 , 1) ; change(n + x , 1 , n * 2 , 1) ;
            lstans = ans[1] + n - 1 ; printf("%d
    ",lstans) ;
        }
        return 0 ;
    }
    
  • 相关阅读:
    pyspark 知识点
    pyspark 读取csv文件创建DataFrame的两种方法
    iOS开发改变字符串中指定字符颜色,大小等等
    iOS开发解决页面滑动返回跟scrollView左右划冲突
    iOS开发自定义试图切换
    iOS开发UIColor,CGColor,CIColor三者的区别和联系
    iOS开发热更新JSPatch
    Swift-创建UIButton(其他UI组件雷同)
    Swift-枚举enum理解
    Swift-闭包理解(二)
  • 原文地址:https://www.cnblogs.com/beretty/p/10768080.html
Copyright © 2011-2022 走看看