首页 > 其他分享 >2022NOIPA层联测23

2022NOIPA层联测23

时间:2022-11-08 19:23:34浏览次数:43  
标签:ch 2022NOIPA 23 int lli maxn 联测 端点 mx

C. 作弊

为了防止改不完题,这个神奇的东西我一定要现在就写!

%%%Chen_jr  一看就知道我又鹤了

设s(l, r)表示在[l, r]之间作一次弊的最大收益,这个东西居然可以优化!!转移方程是f[i] = max(f[i], f[j-1]+s(j, i)),发现每一个时刻只有右端点是i的s是有用的,线段树的一部分就是右端点为i时,左端点为(线段树下标)的s的大小,同时还把f[j-1]记录到了f[j]上,这样就可以让答案都在一个点上维护线段树的区间最值了!

现在就需要维护右端点移动时s的变化。(鹤一下)考虑分开计算每个人的贡献,i对s(i, j)产生贡献当且仅当mx(l, r)属于[li, ri],将其拆成max(mx(l, i), mx(i, r))属于[li, ri],也就是mx(l,  i),mx(i, r)都要<=ri,且其中至少一个>=li。

对于每个i预处理出mx(l, i),mx(i, r)属于[li, ri]的l, r的范围,记为[lri, lli], [rli, rri](因为mx从i向左递增,从i向右递增),第一个l/r表示是谁的范围,第二个l/r表示满足哪个条件(>=li还是<=ri)。具体实现的时候找的是(以l的范围为例)满足a[j]>=l[i]的i左边的最大的j和满足a[k]>r[i]的i左边的最大的k,它+1才是标准的范围,但是恰好可以在线段树上消去贡献时作为起点。

预处理可以用树状数组,下标是值域,val是位置,因为要找值更大的,可以直接往后找,也可以把树状数组翻转过来让a更大的在左边,向左要找val最小的,向右要找val最大的,原来的函数可以直接用,把权值和答案都变成相反的就好,这样负负得正。

当右端点属于[i, ri]时,左端点在[lli, lri]内有贡献;属于[rli, rri]时,左端点在[lli, i[内有贡献,注意[lri, lli]内的贡献不需要重复统计所以从lli+1开始;大于rri时,没有贡献。第一层循环的i既表示讨论到的位置,又表示当前的右端点,一开始先把i更新为f[i-1]修改之后它就变成i了,f[i-1]不是f[i]的初值因为s(i, i)可能不是0。记录以i为转折点的x,在适当的时候去掉x的贡献。

code
#include <bits/stdc++.h>

using namespace std;

//typedef long long ll;你猜为什么过不了编译
const int maxn = 1e5 + 5;

int f[maxn], a[maxn], n, l[maxn], r[maxn];
int ll[maxn], lr[maxn], rl[maxn], rr[maxn];
vector<int> RL[maxn], RR[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct BIT 
{
    int t[maxn];
    int lowbit(int x) {return x & -x;}
    void modify(int x, int val) {x = n - x + 1; while(x <= n) {t[x] = max(t[x], val); x += lowbit(x);}}
    int query(int x) {x = n - x + 1; int ans = 0; while(x) {ans = max(ans, t[x]); x -= lowbit(x);} return ans;}
    void clear() {for(int i=1; i<=n; i++) t[i] = 0;}
}T;

struct seg 
{
    struct node 
    {
        int val, tag;
    }t[maxn<<2];
    void pushdown(int x)
    {
        int ls = x<<1, rs = x<<1|1;
        t[ls].val += t[x].tag;
        t[rs].val += t[x].tag;
        t[ls].tag += t[x].tag;
        t[rs].tag += t[x].tag;
        t[x].tag = 0;
    }
    void pushup(int x)
    {
        t[x].val = max(t[x<<1].val, t[x<<1|1].val);
    }
    void modify(int x, int l, int r, int L, int R, int val)
    {
        if(L <= l && r <= R)
        {
            t[x].val += val; t[x].tag += val;
            return;
        }
        if(t[x].tag) pushdown(x);
        int mid = (l + r) >> 1;
        if(L <= mid) modify(x<<1, l, mid, L, R, val);
        if(R > mid) modify(x<<1|1, mid+1, r, L, R, val);
        pushup(x);
    }
    int query(int x, int l, int r, int L, int R)
    {
        if(L <= l && r <= R) return t[x].val;
        if(t[x].tag) pushdown(x);
        int mid = (l + r) >> 1, ans = 0;
        if(L <= mid) ans = max(ans, query(x<<1, l, mid, L, R));
        if(R > mid) ans = max(ans, query(x<<1|1, mid+1, r, L, R));
        return ans;
    }
}t;

int main()
{
    freopen("cheat.in", "r", stdin);
    freopen("cheat.out", "w", stdout);
    
    n = read();
    for(int i=1; i<=n; i++) a[i] = read();
    for(int i=1; i<=n; i++) l[i] = read(), r[i] = read();
    for(int i=1; i<=n; i++)
    {
        T.modify(a[i], i); ll[i] = T.query(l[i]), lr[i] = T.query(r[i]+1);
    }
    T.clear();
    for(int i=n; i>=1; i--)
    {
        T.modify(a[i], n-i+1); rl[i] = n-T.query(l[i])+1, rr[i] = n-T.query(r[i]+1)+1;
    }
    for(int i=1; i<=n; i++)
    {
        if(rl[i]) RL[rl[i]].push_back(i);
        if(rr[i]) RR[rr[i]].push_back(i);
    }
    for(int i=1; i<=n; i++)
    {
        t.modify(1, 1, n, i, i, t.query(1, 1, n, 1, n));
        if(ll[i]) t.modify(1, 1, n, 1, ll[i], 1);
        if(lr[i]) t.modify(1, 1, n, 1, lr[i], -1);
        for(int x : RL[i]) if(ll[x] < x) t.modify(1, 1, n, ll[x]+1, x, 1);
        for(int x : RR[i]) if(lr[x] < x) t.modify(1, 1, n, lr[x]+1, x, -1);
    }
    printf("%d\n", t.query(1, 1, n, 1, n));

    return 0;
}

 

标签:ch,2022NOIPA,23,int,lli,maxn,联测,端点,mx
From: https://www.cnblogs.com/Catherine2006/p/16870762.html

相关文章

  • 20220923 17. 认识系统服务 (daemons)
    17.1什么是daemon与服务(service)常驻在记体体中的程序,且可以提供一些系统或网络功能,那就是服务系统为了某些功能必须要提供一些服务(不论是系统本身还是网络方面),这个......
  • 20221107 23. X Window 设置介绍
    在Linux上头的图形接口我们称之为XWindowSystem,简称为X或X11啰!为何称之为系统呢?这是因为X窗口系统又分为Xserver与Xclient,既然是Server/Client(主从架......
  • 223201062522-软件工程基础Y- 实验一 刘晋
      沈阳航空航天大学软件工程基础实验报告实验名称:实验一实验题目:个人项目完成时间:2022年11月1实验内容及要求1.1教学内容及要求建立个人博客,完......
  • 汉化:PS磨皮插件DR5白金版 支持ps2023
    DeliciousRetouch5白金版formac(PS磨皮插件DR5)是一款非常受欢迎的PS一键磨皮插件,带有滑块和选项的内置对话框使您可以控制所有重要功能。dr5插件提供了人像磨皮、平滑......
  • 兼容替代CP2102 USB 转串口芯片 CH9102 USB 转RS485/9线TTL/RS232串口
    今天来讲讲一颗USB总线的转接芯片--CH9102,能够替代ti的CP2101。该芯片实现USB转异步串口。提供了常用的MODEM联络信号,用于为计算机扩展异步串口,或者将普通的串口设备......
  • 23个Git实用技巧及命令汇总
    Git是一个非常强大的工具,它包含丰富的工具用以维护项目。本文整理汇总了23个 Git日常使用的命令,希望这些内容能够对大家有所帮助。1、新建创建一个新的git版本库。这......
  • 2022NOIPA层联测22
    A.极源流体上和下,左和右是等效的,只考虑下和右。操作顺序不影响结果,按任意顺序操作x次右,y次下后,一个黑格一定会变成一个长为x,宽为y的矩形。可以用两个队列记录位置,这样可......
  • NOIP联测22
    T1.极源流体正解是\(LCT\)维护最小生成树,显然我是不会的。性质一:向上和向下等价,向左和向右等价,所以可以只考虑向右下方扩展。性质二:向下和向右操作顺序可以交换,那么可以......
  • [LeetCode] 1323. Maximum 69 Number
    Youaregivenapositiveinteger num consistingonlyofdigits 6 and 9.Return themaximumnumberyoucangetbychanging atmost onedigit(6 becomes......
  • Javascript(笔记23) - DOM基本操作 - 遍历节点树的方法
    Javascript(笔记23)-DOM基本操作-遍历节点树DOM的节点可以形成一个类型树的结构遍历节点树节点的类型上图看的是HTML的结构,主要指的是元素节点,但在DOM结构里,节点可不止......