• P8539 「Wdoi-2」来自地上的支援 题解


    思路

    根据题意,如果每次询问选中的为第 x" role="presentation">x 个数,那么前 x1" role="presentation">x1 次操作一定不会选中第 x" role="presentation">x 个数。(感觉在说废话。

    同样,因为第 x" role="presentation">x 个数必须被选中 k" role="presentation">k 次,根据题意,不难发现这 k" role="presentation">k 次选中一定是从第 x" role="presentation">x 次操作到 x+k1" role="presentation">x+k1 次操作被选中。因为如果某个数在某次操作时没有被选中,那么他在后面的操作中肯定不会再次被选中。

    根据上面的思路,我们要修改的最小值 s" role="presentation">s 必须大于等于前 x1" role="presentation">x1 个数进行 x1" role="presentation">x1 次操作后的最大值,我们可以用一个前缀数组来维护,数组的每个值 prei" role="presentation">prei 表示前 i1" role="presentation">i1 个数进行 i1" role="presentation">i1 次操作后的最大值,然后再向后枚举 k1" role="presentation">k1 个数,每次都和进行过若干次操作后的最大值比较,如果枚举到的值比最大值大,就讲当前的最大值修改为枚举到的值加一(操作的第二个性质),这样就可以得到答案。

    这时你就可以得到 65" role="presentation">65 分的好成绩。

    优化

    很显然,对于上面向后枚举 k1" role="presentation">k1 个数的操作是可以进行优化的。

    因为要区间查询最大值,所以不妨考虑一下线段树,但现在问题出现在如果维护最大值上。

    我们可以考虑在维护线段树时同时记录下最大值和最大值所在的坐标。然后在两个数相比较的时候,比较 ai+(ji)×v" role="presentation">ai+(ji)×vaj" role="presentation">aj 的大小(ij" role="presentation">ij)。根据这样比较的结果选出最大值来,这样我们只需要把 s" role="presentation">s 修改为 max{prex,ap(px)×v+1}" role="presentation">max{prex,ap(px)×v+1}p" role="presentation">p 表示最大值所在的下标)即可。

    代码

    #include 
    #define int long long
    #define ls x<<1
    #define rs x<<1|1
    #define N 2000010
    using namespace std;
    
    struct node {
    	int val, st;
    };
    int n, m, v, a[N], pre[N], ans1, ans2;
    node maxn[N << 2];
    
    node max(node x, node y) {
    	if (x.st > y.st) {
    		if ((x.st - y.st)*v + y.val < x.val) {
    			return x;
    		} else {
    			return y;
    		}
    	} else {
    		if ((y.st - x.st)*v + x.val < y.val) {
    			return y;
    		} else {
    			return x;
    		}
    	}
    
    }
    
    void bulid(int x, int l, int r) {
    	if (l == r) {
    		maxn[x] = node{a[l], l};
    		return;
    	}
    
    	int mid = l + r >> 1;
    	bulid(ls, l, mid);
    	bulid(rs, mid + 1, r);
    	maxn[x] = max(maxn[ls], maxn[rs]);
    }
    
    node query(int x, int l, int r, int L, int R) {
    	if (l >= L && r <= R) {
    		return maxn[x];
    	}
    
    
    	int mid = l + r >> 1;
    
    	if (R <= mid) {
    		return query(ls, l, mid, L, R);
    	} else if (L > mid) {
    		return query(rs, mid + 1, r, L, R);
    	} else {
    		return max(query(ls, l, mid, L, R), query(rs, mid + 1, r, L, R));
    	}
    }
    
    signed main() {
    	scanf("%lld%lld%lld", &n, &m, &v);
    	int maxn = 0;
    
    	for (int i = 1; i <= n; i++) {
    
    		scanf("%lld", &a[i]);
    		pre[i] = maxn;
    		maxn = max(maxn, a[i]) + v;
    	}
    
    	bulid(1, 1, n);
    
    	while (m--) {
    		int x, k;
    		scanf("%lld%lld", &x, &k);
    
    		if (k > n - x + 1) {
    			continue;
    		}
    
    		int s = pre[x];
    		if(k==1){
    			ans1 ^= s;
    			ans2 += s;
    			continue;
    		}
    		node tmp = query(1, 1, n, x + 1, x + k - 1);
    
    		if (s <= tmp.val - (tmp.st - x)*v) {
    			s = tmp.val - (tmp.st - x) * v + 1;
    		}
    
    		ans1 ^= s;
    		ans2 += s;
    	}
    
    	printf("%lld %lld", ans1, ans2);
    	return 0;
    }

    __EOF__

  • 本文作者: Dregen_Yor
  • 本文链接: https://www.cnblogs.com/Dregen-Yor/p/16690428.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    引导滤波融合matlab
    TFT-LCD移植LVGL详细过程记录
    WRF-Chem在大气环境(PM2.5、臭氧)、能见度、城市化方面应用
    通信原理学习笔记6-4:数字解调——抽样判决的译码准则(最大后验概率准则MAP、最大似然准则ML、最小二乘/最小平方准则LS、最小距离准则)
    刷题记录:牛客NC16746神奇盘子
    OpenCASCADE7.6编译
    2023年国自然植物科学相关面上项目信息公布(小麦、大麦、棉花、大豆、玉米)
    Mysql之常用函数、聚合函数&合并(union&union all)【第四篇】
    数学基础之曲线拟合
    云原生环境该怎样解决网络安全问题
  • 原文地址:https://www.cnblogs.com/Dregen-Yor/p/16690428.html