首页 > 其他分享 >CF56E 题解

CF56E 题解

时间:2024-07-25 21:40:56浏览次数:13  
标签:max int 题解 upd pos mid ans CF56E

题面

设骨牌 \(i\) 倒下之后会连带压倒 \([i+1,r_i]\) 的骨牌,那么有

\(z_i=\max_{j=i+1}^{r_i}z_j+(j-i)\)

考虑线段树优化 dp,但是 \((j-i)\) 不好维护,所以套路地修改式子,得到:

\(z_i+i=\max_{j=i+1}^{r_i}(z_j+j)\)

所以线段树维护 \(z_i+i\) 的区间最大值即可,\(r_i\) 可以二分求出。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e5 + 5;

struct sgt
{
    int a[N << 2];
    void pu(int x)
    {
        a[x] = max(a[x << 1], a[x << 1 | 1]);
    }
    void upd(int q, int l, int r, int x, int v)
    {
        if(l == r) return a[x] = v, void();
        int mid = l + r >> 1;
        if(mid >= q) upd(q, l, mid, x << 1, v);
        else upd(q, mid + 1, r, x << 1 | 1, v);
        pu(x);
    }
    int qry(int ql, int qr, int l, int r, int x)
    {
        if(ql <= l && r <= qr) return a[x];
        int mid = l + r >> 1, ans = 0;
        if(mid >= ql) ans = max(ans, qry(ql, qr, l, mid, x << 1));
        if(mid < qr) ans = max(ans, qry(ql, qr, mid + 1, r, x << 1 | 1));
        return ans;
    }
    void build(int l, int r, int x)
    {
        if(l == r) return a[x] = l, void();
        int mid = l + r >> 1;
        build(l, mid, x << 1);
        build(mid + 1, r, x << 1 | 1);
        pu(x);
    }
} t;

struct node{int pos, h, id;} a[N];
int pos[N], ans[N], id[N];

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    int n; cin >> n;
    t.build(1, n, 1);
    for(int i = 1; i <= n; i ++) cin >> a[i].pos >> a[i].h, a[i].id = i;
    sort(a + 1, a + n + 1, [](auto &x, auto &y) {return x.pos < y.pos;});
    for(int i = 1; i <= n; i ++) id[a[i].id] = i;
    for(int i = 1; i <= n; i ++) pos[i] = a[i].pos;
    t.upd(n, 1, n, 1, n + 1);
    ans[n] = 1;
    for(int i = n - 1; i >= 1; i --)
    {
        int r = lower_bound(pos + 1, pos + n + 1, a[i].pos + a[i].h) - pos - 1;
        if(r == i)
        {
            t.upd(i, 1, n, 1, i + 1);
            ans[i] = 1;
            continue;
        }
        int k = t.qry(i + 1, r, 1, n, 1);
        t.upd(i, 1, n, 1, k);
        ans[i] = k - i;
    }
    for(int i = 1; i <= n; i ++) cout << ans[id[i]] << " ";

    return 0;
}

标签:max,int,题解,upd,pos,mid,ans,CF56E
From: https://www.cnblogs.com/adam01/p/18324194

相关文章

  • CF86D 题解
    题面看起来线段树之类的不好维护,但是移动区间的增量很好求,数据范围也能过,那么直接莫队就行了。设加入或删除了值\(x\),设原来区间内有\(cnt_x\)个,现在有\(cnt'_x\)个,那么增量就是\(x((cnt'_x)^2-(cnt_x)^2)\),直接求就好了。复杂度\(O(t\sqrtn)\)。#include<bits/stdc+......
  • CF567E 题解
    题面考虑如何一条边是必经之路:设\(cntl_i\)为从\(s\)到\(i\)走最短路的方案数,\(cntr_i\)为从\(i\)到\(t\)最短路方案数。由乘法原理,如果对于边\(e_i=(u,v)\),\(cnt_t=cnt_u\timescntr_v\),则\(e_i\)是最短路上的必经边,输出Yes即可。如果\(cnt_u\timescntr_v=0......
  • 【题解】Solution Set - 杂题选讲「刘君实」
    https://www.becoder.com.cn/contest/5423「HNOI2012」集合选数感觉差不多会。7/25sh杂题听课情况NOI2018冒泡排序【40】几乎不会麦田里的守望者【40】打表找规律、最后dp不太理解星空列车【40】完全不会WereYouLast:知道怎么做,但是不知道为什么是对的A......
  • CF467E 题解
    题面给出这种限制,我们只能4个4个考虑。令\(f_i\)为考虑到\(a_i\),最长的\(b\)序列长\(4f_i\)。令\(mx_i\)为以\(a_i\)结尾的最短连续子序列包含\(x\y\x\y\)的(不一定连续的)结构的左端点。于是有\(f_i=\max_{j=1}^{mx_i-1}f_j+4\)。用前缀和优化:\(g_i=\max......
  • CF594A 题解
    题面来个不一样的证明。根据样例,我们可以有一个直觉:两点之间一定距离\(\fracn2\),答案为这样的点对之间\(\Deltax\)的最小值。直接交上去,发现这是对的。为什么呢?先证明上界:先手可以让答案小于等于两点距离\(\fracn2\)点对的\(\Deltax\)的最小值。这是容易的:先手只......
  • 题解:Codeforces Round 961 (Div. 2) B1&B2
    本题含有B1和B2两个难度版本。由于关系相近,我把他们放在同一篇博客中,可自行选择观看B1.Bouquet(EasyVersion)timelimitpertest:1.5secondsmemorylimitpertest:512megabytesinput:standardinputoutput:standardoutputThisistheeasyversionoftheprobl......
  • CF568C New Language 题解
    Description将\(\texttt{a}\sim\texttt{a}+l-1\)这\(l\)个字符分成\(\texttt{V,C}\)两个集合。你需要构造一个长度为\(n\)且满足\(m\)个限制且不小于另一个长度为\(n\)的字符串\(s\)的最小字符串。每一个限制为若字符串的第\(p_1\)个位置上的字符\(\in......
  • CF22E 题解
    题面注意到题目给的图为基环树森林。因为一个(\(n>1\))的强连通图每个点都要有出度和入度,所以:对于每个基环树,叶子结点是没有入度的,所以一定要有一条从环上出发的路径经过这个点。对于基环树的环,注意到它缩点后没有出度,所以一定要有一条出边。注意到叶子结点的需求和根节点相反,......
  • 题解:AT_arc116_e [ARC116E] Spread of Information
    题目链接思路看到最大值最小首先可以想到二分,发现答案具有单调性,那么思考如何在\(O(n)\)的时间内判断是否合法。考虑贪心,在最远没覆盖的点的距离和要判断的\(mid\)刚好相等的时侯再选择一定不劣,因为这样覆盖的点最多,那么从叶子节点向上回溯,处理它的所有儿子,判断是否选择该......
  • LG3107 [USACO14OPEN] Odometer S 题解 (数位DP+容斥)
    题意定义一个数是神奇的当且仅当这个数中有一个数位出现了一半及以上,比如112,2233。求\([l,r]\)中有多少个好的数字,\(100\lel,r\le10^{18}\)。题解考虑数位DP,先把答案转为\(Ans(r)-Ans(l-1)\),我们钦定一个数\(k\)让他必须出现多于一半,然后我们想求\([1,x]\)中有多少......