• [HNOI/AHOI2018]转盘


    题目链接

    题意:

    给你一个(n)元环,你可以在0时刻从任意一个位置出发,每一秒可以选择往后或者留在原地
    每个点有个参数(T_i),当你走到(i)的时间(t>=T_i)时你就可以把i标记
    问你把整个环上的点都标记最小需要多长时间,带修改(T_i),强制在线


    好难的题。
    首先,有等待操作不太好弄。
    可以发现:在总时间一定的情况下,到每个点越晚越好。
    所以,可以把所有等待都移到起点处,解不会变差。
    由于是环,破环为链处理。
    如果在(s)时间在(i (1<=i<=n))出发,那么到(j (i<=j<i+n))的时间为(s+(j-i))。根据要求,得(s+(j-i)>=T_j)
    (s=max(T_j-j)+i (i<=j<i+n))。总时间为(max(T_j-j)+i+n-1 (i<=j<i+n))
    就是要找一个(i (1<=i<=n)),使得(max(T_j-j)+i+n-1 (i<=j<i+n))最小。
    (A_j=T_j-j),则式子变为(max(A_j)+i+n-1 (i<=j<i+n))
    这样就得出的答案的式子。
    发现(max(A_j)+i+n-1 (i<=j<i+n))等于(max(max(A_j) (i<=j<=n),max(A_j) (n+1<=j<i+n)+i+n-1)
    而由于(A)的后半段是由前半段复制过来并减(n)
    所以(max(A_j) (i+1<=j<=n+n)<max(max(A_j) (i<=j<=n))
    所以式子可以变为(max(A_j)+i+n-1 (i<=j<=n+n))(即后缀最值)。
    但是有修改,这样还是不好维护答案。增加很好做,区间覆盖即可,但因为有减小的操作,减小后,修改的段会很多,无法处理。
    我们发现,在(max(A_j))一定时,(i)越小越好。
    所以维护所有让(max(A_j))变大的(j),就是从后往前的单调递增序列。
    设这个序列为(W_i),那么若(i={W_x}+1),则(max(A_j)=A_{W_{i+1}})
    这样,式子变为(A_{W_{i+1}}+{W_i}+1+i+n-1),即(A_{W_{i+1}}+{W_i}+i+n)
    单调递增序列可以用线段树维护,方法如下:
    首先,单调递增序列只是用于合并答案,所以保存(W)的第一个和最后一个,还有这段序列的答案就行。
    维护每个节点的(max),单调递增序列,还有整体考虑时左子节点的单调递增序列。
    设计一个(getst(l,r,x))表示求(l~r)的元素只考虑>(x)的答案。
    若右儿子的最值不大于x,则不用考虑右儿子,只考虑左儿子即可。
    否则,左儿子的递增序列一定完全包含在答案中,只考虑右儿子即可。
    考虑(pushup)操作的实现:只要用左儿子的(getst)加上右儿子即可。
    每次(pushup),时间复杂度为(O(logn)),总时间复杂度为(O(nlog^2n))
    代码还不算太难写,主要是推导比较复杂。

    #include <stdio.h> 
    #define max(a, b)(a > b ? a: b)
    #define min(a, b)(a < b ? a: b) 
    int sz[200010],inf = 999999999;
    struct SJd {
    	int x,y,mi;
    	SJd() {}
    	SJd(int a) {
    		x = y = a;
    		mi = inf;
    	}
    	SJd(int l, int r, int w) {
    		x = y = -1;
    		mi = inf;
    		for (int i = r; i >= l; i--) {
    			if (sz[i] > sz[w]) {
    				if (y == -1) x = y = i;
    				else x = i;
    				mi = min(mi, sz[w] + i);
    				w = i;
    			}
    		}
    	}
    };
    SJd operator + (SJd a, SJd b) {
    	if (a.x == -1) return b;
    	if (b.x == -1) return a;
    	SJd rt;
    	rt.x = a.x;
    	rt.y = b.y;
    	rt.mi = min(a.mi, b.mi);
    	rt.mi = min(rt.mi, sz[b.x] + a.y);
    	return rt;
    }
    SJd jd[400010],zz[400010];
    int ma[400010],wz[400010];
    SJd getst(int i, int l, int r, int w) {
    	if (r - l <= 4) return SJd(l, r - 1, w);
    	int m = (l + r) >> 1;
    	if (ma[(i << 1) | 1] <= sz[w]) return getst(i << 1, l, m, w);
    	else return zz[i] + getst((i << 1) | 1, m, r, w);
    }
    void pushup(int i, int l, int r) {
    	ma[i] = max(ma[i << 1], ma[(i << 1) | 1]);
    	if (ma[i] == ma[i << 1]) wz[i] = wz[i << 1];
    	else wz[i] = wz[(i << 1) | 1];
    	int m = (l + r) >> 1;
    	zz[i] = getst(i << 1, l, m, jd[(i << 1) | 1].x);
    	jd[i] = zz[i] + jd[(i << 1) | 1];
    }
    void getddz(int i, int l, int r) {
    	ma[i] = sz[l];
    	wz[i] = l;
    	jd[i] = SJd(l);
    }
    void jianshu(int i, int l, int r) {
    	if (l + 1 == r) {
    		getddz(i, l, r);
    		return;
    	}
    	int m = (l + r) >> 1;
    	jianshu(i << 1, l, m);
    	jianshu((i << 1) | 1, m, r);
    	pushup(i, l, r);
    }
    void xiugai(int i, int l, int r, int j) {
    	if (l + 1 == r) {
    		getddz(i, l, r);
    		return;
    	}
    	int m = (l + r) >> 1;
    	if (j < m) xiugai(i << 1, l, m, j);
    	else xiugai((i << 1) | 1, m, r, j);
    	pushup(i, l, r);
    }
    void xiugai(int x, int y, int n) {
    	sz[x] = y - x;
    	sz[x + n] = y - (x + n);
    	xiugai(1, 1, n + 1, x);
    }
    int getans(int n) {
    	SJd rt;
    	rt.mi = ma[1];
    	rt.x = wz[1] + n;
    	rt.y = -1;
    	rt = getst(1, 1, n + 1, wz[1] + n) + rt;
    	return rt.mi + n;
    }
    int main() {
    	int n,m,p;
    	scanf("%d%d%d", &n, &m, &p);
    	for (int i = 1; i <= n; i++) {
    		int a;
    		scanf("%d", &a);
    		sz[i] = a - i;
    		sz[i + n] = a - (i + n);
    	}
    	jianshu(1, 1, n + 1);
    	int la = getans(n);
    	printf("%d
    ", la);
    	for (int i = 0; i < m; i++) {
    		int x,y;
    		scanf("%d%d", &x, &y);
    		if (p == 1) {
    			x ^= la;
    			y ^= la;
    		}
    		xiugai(x, y, n);
    		la = getans(n);
    		printf("%d
    ", la);
    	}
    	return 0;
    }
    
  • 相关阅读:
    开发实践思考(一)
    记一次前端适配后台接口改造的开发小结
    百度地图AK申请
    Idea 不更新pom.xml中的jar包
    java junit @Test 变量共享问题 --springboot 中的Controller静态变量可以共享
    Java如何对HashMap按值进行排序--非String int 类型时
    Salesforce Integration 概览(七) Data Virtualization数据可视化
    Salesforce Integration 概览(六) UI Update Based on Data Changes(UI自动更新基于数据变更)
    Salesforce Integration 概览(五) Remote Call-In(远程操作 外部->salesforce)
    Salesforce Integration 概览(四) Batch Data Synchronization(批量数据的同步)
  • 原文地址:https://www.cnblogs.com/lnzwz/p/11342469.html
Copyright © 2020-2023  润新知