zoukankan      html  css  js  c++  java
  • 「AHOI / HNOI2018」转盘(找性质+线段树维护单调栈)

    https://loj.ac/problem/2495

    考虑最优的决策,有一种是一直往右走,不在一个点上等,为什么是对的呢?

    证明:如果在一个点上等一刻,不如把起点往前移一位。

    破环为链复制一遍以方便记答案。

    首先需要的时间一定(ge n-1),不妨枚举倒数第(n)个点是(i),再考虑走到(i)的时间最小是(t)才能在剩下(n-1)步标记所有点。

    写成式子就是(forall jin[i,i+n-1] t+i-j>=t[j])
    (t=max(t[j]+j-i)(jin[i,i+n-1]))

    不难发现(jin [i,i+n-1])的限制可以改为(jin [i,2n]),因为(t[j+n]-(j+n)< t[j]-j)

    写成总式子:
    (Ans=n+1+min_{i=1}^n i+max_{j=1}^{2n}t[j]-j)
    (t[j]-j)看成整体,相当于顺着做一个递减的单调栈,顺便统计一下答案。

    用《楼房重建》那种线段树维护即可。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int N = 2e5 + 5;
    
    #define i0 i + i
    #define i1 i + i + 1
    
    int n, m, tp;
    
    int a[N], x, y;
    
    int t[N * 4], fx[N * 4];
    int query(int i, int x, int y, int p) {
    	if(x == y) {
    		return x <= n ? max(t[i], p) + x : 1e9;
    	}
    	int m = x + y >> 1;
    	if(p > t[i1]) {
    		int v = (m + 1 <= n) ? m + 1 + p : 1e9;
    		return min(v, query(i0, x, m, p));
    	} else {
    		return min(fx[i], query(i1, m + 1, y, p));
    	}
    }
    int pl, pr, px;
    void add(int i, int x, int y) {
    	if(y < pl || x > pr) return;
    	if(x == y) {
    		t[i] = px; return;
    	}
    	int m = x + y >> 1;
    	add(i0, x, m); add(i1, m + 1, y);
    	t[i] = max(t[i0], t[i1]);
    	fx[i] = query(i0, x, m, t[i1]);
    }
    
    void xiu(int x) {
    	pl = pr = x, px = a[x] - x;
    	add(1, 1, 2 * n);
    	pl = pr = x + n, px = a[x] - (x + n);
    	add(1, 1, 2 * n);
    }
    
    int main() {
    	scanf("%d %d %d", &n, &m, &tp);
    	fo(i, 1, n) {
    		scanf("%d", &a[i]);
    		xiu(i);
    	}
    	int ans = query(1, 1, 2 * n, -1e9) + n - 1;
    	pp("%d
    ", ans);
    	fo(ii, 1, m) {
    		scanf("%d %d", &x, &y);
    		if(tp) x ^= ans, y ^= ans;
    		a[x] = y;
    		xiu(x);
    		ans = query(1, 1, 2 * n, -1e9) + n - 1;
    		pp("%d
    ", ans);
    	}
    }
    
  • 相关阅读:
    字符串转json
    如何解决写好的脚本上传Linux执行出错?
    Windows查看端口并开放端口
    解决mysql遇到非root权限无法登录mysql数据库的问题
    raid配置
    Python实现根据时间移动/复制一个文件夹的文件--模拟大并发数据
    ffmpeg基本命令学习
    pytest学习--pytest的skip和skipif
    多项式全家桶学习笔记(How EI's poly works)
    具体数学难度评分
  • 原文地址:https://www.cnblogs.com/coldchair/p/12690076.html
Copyright © 2011-2022 走看看