首页 > 其他分享 >P11119 [ROI 2024 Day 2] 保持连接

P11119 [ROI 2024 Day 2] 保持连接

时间:2024-10-03 11:22:43浏览次数:1  
标签:ROI min int max 贡献 2024 P11119 Day

P11119 [ROI 2024 Day 2] 保持连接

设 \(L_i,R_i\) 分别表示覆盖了 \(i\) 的的线段中最靠左的左端点和最靠右的右端点,特殊的,如果没有覆盖,则 \(L_i=R_i=i\)。显然所有 \(R_i\) 就刻画了一种局面。

如果没有 \(X\) 的操作,设 \(g_i\) 表示从 \(i\) 出发到 \([i,n]\) 的重新连接的次数之和,转移为 \(g_i=n-R_i+g_{R_i+1}\),那么答案就是 \(\sum g_i\)。

加上 \(X\) 的操作,考虑其对位置 \(i\) 的影响,设 \(p\) 为覆盖了 \(\min(n,i+X)\) 的线段的最靠左的左端点,那么有影响的是跳到过 \([\max(1,i-X),p-1]\) 的区间的点,它们的 \(R\) 会改变为 \(\min(n,i+X)\),接下来要求出经过此区间的点的个数,减去他们接下来原本的贡献,加上新的贡献。

设 \(f_i\) 表示以 \([1,i]\) 为起点,经过 \(i\) 的起点个数,转移为 \(f_i=1+\sum\limits_{R_j+1=i}f_j\)。设经过该区间的点数为 \(c\),他们接下来原本的贡献之和为 \(s\),原本不操作 \(X\) 的答案为 \(S\),那么位置 \(i\) 的答案为 \(S-s+c(n-r+g_{r+1})\)。考虑 \(i\) 从小到大枚举,设 \(l=\max(1,i-X)\),当 \(l>1\) 时,在树状树组的位置 \(R_{l-1}+1\) 处加入贡献,这样可以保证加入 \(x\) 是第一次跳到区间中的,特殊的,以 \(i\) 为起点的贡献可以在扫描之前加入。

实现时可以开两棵树状树组维护个数和贡献,代码非常精简。

#include <bits/stdc++.h>
#define int long long
#define lb(x) (x & (-x))

using namespace std;

bool START;

const int N = 1e6 + 5;

int n, X, a[N], L[N], R[N];
int f[N], g[N], S, ans;

struct bit {
  int c[N];
  void add(int x, int k) {for (; x <= n; x += lb(x)) c[x] += k;}
  int ask(int x) {int s = 0; for (; x; x -= lb(x)) s += c[x]; return s;}
} t1, t2;

bool END;

signed main() {
  cin >> n >> X; for (int i = 1; i <= n; ++i) L[i] = i, R[i] = i;
  for (int i = 1; i <= n; ++i) {
    cin >> a[i]; int r = min(n, i + a[i]), l = max(1ll, i - a[i]);
    L[r] = min(L[r], l), R[l] = max(R[l], r);
  }
  for (int i = n - 1; i; --i) L[i] = min(L[i], L[i + 1]);
  for (int i = 2; i <= n; ++i) R[i] = max(R[i], R[i - 1]);
  for (int i = n - 1; i; --i) g[i] = n - R[i] + g[R[i] + 1];
  for (int i = 1; i <= n; ++i) f[i]++, f[R[i] + 1] += f[i];
  for (int i = 1; i <= n; ++i) S += g[i];
  ans = S;

  for (int i = 1; i <= n; ++i) t1.add(i, g[i]), t2.add(i, 1);
  for (int i = 1; i <= n; ++i) {
    int p = (i + X <= n ? L[i + X] : n + 1);
    int l = max(1ll, i - X), r = min(n, i + X);
    if (l > 1) {
      int t = l - 1;
      if (R[t] + 1 <= n) t1.add(R[t] + 1, f[t] * g[R[t] + 1]), t2.add(R[t] + 1, f[t]);
    }
    if (X <= a[i]) continue;
    if (p <= l) continue;
    int s = S - (t1.ask(p - 1) - t1.ask(l - 1)) + (t2.ask(p - 1) - t2.ask(l - 1)) * (n - r + g[r + 1]);
    ans = min(ans, s);
  }
  cout << ans << endl;
  return 0;
}

标签:ROI,min,int,max,贡献,2024,P11119,Day
From: https://www.cnblogs.com/Tagaki-san/p/18445502

相关文章

  • 2024秋季个人阅读计划
    本学期计划阅读三本书,分别为《代码大全》、《人件集》和《用户故事与敏捷方法》,以下我本学期的阅读计划第4周:阅读:《代码大全》第1-3章阅读笔记1:10月4日第5周:阅读:《代码大全》第4-6章阅读笔记2:10月11日第6周:阅读:《代码大全》第7-10章阅读笔记3:10月18日第7周:阅读:......
  • 微软推送Windows 11 2024更新:新增多项AI体验 NPU终于有了用武之地
    10月3日消息,近日,微软开始向广大用户全面推送Windows112024更新。其实按照惯例应被成为Windows1124H2更新,但由于微软放弃了以往1年2次重大版本更新周期,整个2024年只更新了这一个大版本,因此被设定为“Windows112024更新”。2024更新包含了Windows11中许多小而实用的新增......
  • Android 11.0 framework默认沉浸式导航栏功能实现
    1.前言在11.0的系统rom定制化开发中,在实现导航栏的某些定制化开发中,在某些产品需要实现沉浸式导航栏,就是需要app能全屏显示同样也能显示导航栏,接下来就来分析下相关的功能实现如图:2.framework默认沉浸式导航栏功能实现的核心类frameworks\base\core\java\android\a......
  • 20241002每日一题洛谷P1563
    粗看题目我靠,什么方向还变来变去的(哭泣核心思想:圈内右数,圈外左数为整体逆时针数;圈外右数,圈内左数为整体顺时针数运用结构体就有了第一版源码://///define_CRT_SECURE_NO_WARNINGS1include<stdio.h>includestructpeople{intface;charname[12];};intmain(){in......
  • 20240920
    TryandCry我们肯定是尽可能的让前\((n-1)\)个多拿,但是有可能这个有一些一样的,所以向上取整即可#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e6+5;intt,n;voidSolve(){cin>>n;inttmp=((n*(n-1)/......
  • 2024/10/2 CSP-S模拟赛
    B好题。这题其实是原题,在大工VS辽实的T3里出现过,基本是一摸一样。对于观看这个题解呢,我的理解是把两个结合起来观看,分别是这个和这个,结合起来看的话无论是从感官还是从方便理解来看都很舒服。好了,接下来我们说一下这个题的思路。你考虑,你在一段长度为\(m\)的区间里至少要选......
  • 2024初秋集训——提高组 #29
    C.卡片放置题目描述有一些卡片,写着两个数字\(A_i,B_i\)。你要将这些这些卡片排列,其对于你的分数为\(\max(A_i,B_i)\cdoti\),对于对手的分数为\(\min(A_i,B_i)\cdot(N-i+1)\)。求令你的分数减对方分数的最大的方案数。思路我们来拆式子,这里令\(A_i\geB_i\):\[\begin{arr......
  • CTB2024
    活动官网https://www.chinathinksbig.com/ToDoIMPORTANT10.14提前批报名截止确认要参加的话赶紧把钱交了先注意:付钱(1490好贵)之后才能组队在国庆期间开个会大致考虑一下课题,尽量可以拐一下以下几个点弱势群体环境保护文化保护和传承一些东西数据科技相关......
  • 20241002测试
    move题面:\(T\)组数据,每组数据有\(n\)个数轴上的点\(a_1,a_2,\dots,a_n\)。从原点开始,每次选择一个点未被选择过的点,如果当前在这个点上,那么分数加\(1\),否则向这个点移动\(1\)格。问最高分数。题解:容易发现,要么先往左再往右,要么先往右再往左。先考虑第一种情况,枚举左端......
  • 20241002
    bwtree我们可以设\(dp_{i,0/1}\)表示当前考虑至哪个点,这个节点的子树内选了几个叶子节点#include<bits/stdc++.h>usingnamespacestd;constintN=1e5+5,INF=1e9;intn,a[N],dp[N][2];vector<int>g[N];voiddfs(intu,intf){dp[u][0]=(a[u]=......