首页 > 其他分享 >Codeforces 264E Roadside Trees

Codeforces 264E Roadside Trees

时间:2024-02-28 21:37:42浏览次数:30  
标签:10 val int upd Codeforces Trees T1 Roadside id

首先考虑时间增长的问题,设第 \(i\) 棵树的种植时间为 \(t_i\)。
那么第 \(x\) 棵树比第 \(y\) 棵树高就是 \(h_x + (t_y - t_x) > h_y\),也就是 \(h_x - t_x > h_y - t_y\)。
所以可以直接用 \(h_i - t_i\) 当作第 \(i\) 棵树的高度,即 \(h'_i\leftarrow h_i - t_i\)。

对于增加,考虑用上 \(h_i\le 10\) 个性质。
因为有 \(h'_i\) 互不相同,这说明 \(< h'_i\) 的树只有至多 \(9\) 颗。
记 \(f_i\) 为高度为 \(i\) 的树开头的最长上升子序列长度。
可以知道实际上只需要更改至多 \(10\) 棵树的 \(f_i\) 即可。
因为对于 \(h'_j > h'_i\) 的 \(f_j\) 因为 \(h\) 的大小关系就不可能产生改变。
于是可以考虑暴力拎出这至多 \(10\) 棵树算一下 \(f_i\) 即可。
可以用线段树优化。

对于删除,同样考虑用上 \(x\le 10\) 这个限制。
相同的,只需要暴力拎出来前 \(x\) 颗树删掉第 \(x\) 颗剩下 \(x - 1\) 颗暴力算一遍即可。
但是注意这里是下标,所以维护的是 \(g_i\) 意味下标为 \(i\) 开头的最长上升子序列的长度。
同样用线段树维护一下即可。

可以用 set 存下树的高度与下标。

时间复杂度 \(O(mk(\log n + \log m))\),\(k\) 为 \(h_i, x_i\) 的上界,这里为 \(10\)。

#include<bits/stdc++.h>
const int maxn = 2e5 + 20;
struct segtr {
    int mx[maxn * 2];
    #define mid ((l + r) >> 1)
    inline int index(int l, int r) {return l + r | l != r;}
    inline void pushup(int l, int r) {mx[index(l, r)] = std::max(mx[index(l, mid)], mx[index(mid + 1, r)]);}
    inline void upd(int x, int y, int l = 1, int r = 2e5 + 10) {
        if (l == r) return mx[index(l, r)] = y, void();
        x <= mid ? upd(x, y, l, mid) : upd(x, y, mid + 1, r);
        pushup(l, r);
    }
    inline int qry(int x, int l = 1, int r = 2e5 + 10) {
        if (l == r) return mx[index(l, r)];
        return mid < x ? qry(x, mid + 1, r) : std::max(qry(x, l, mid), mx[index(mid + 1, r)]);
    }
} T1, T2;
int H_[maxn], id_[maxn];
std::set<int> id, H;
int main() {
    int n, m; scanf("%d%d", &n, &m);
    for (int T = 1; T <= m; T++) {
        int op; scanf("%d", &op);
        if (op == 1) {
            int x, h; scanf("%d%d", &x, &h);
            h += m - T;
            id_[h] = x, H_[x] = h;
            std::vector<int> P;
            while (! H.empty() && *H.begin() < h) {
                int i = *H.begin();
                P.push_back(i), H.erase(H.find(i)), id.erase(id.find(id_[i]));
            }
            for (int i : P) T1.upd(id_[i], 0), T2.upd(i, 0);
            P.push_back(h);
            std::reverse(P.begin(), P.end());
            for (int i : P) {
                int val = T1.qry(id_[i]) + 1;
                T1.upd(id_[i], val), T2.upd(i, val);
            }
            for (int i : P) id.insert(id_[i]), H.insert(i);
        } else {
            int x; scanf("%d", &x);
            std::vector<int> P;
            while (x--) {
                int i = *id.begin();
                P.push_back(i), id.erase(id.find(i)), H.erase(H.find(H_[i]));
            }
            for (int i : P) T1.upd(i, 0), T2.upd(H_[i], 0);
            P.pop_back();
            std::reverse(P.begin(), P.end());
            for (int i : P) {
                int val = T2.qry(H_[i]) + 1;
                T1.upd(i, val), T2.upd(H_[i], val);
            }
            for (int i : P) id.insert(i), H.insert(H_[i]); 
        }
        printf("%d\n", T1.qry(1));
    }
    return 0;
}

标签:10,val,int,upd,Codeforces,Trees,T1,Roadside,id
From: https://www.cnblogs.com/rizynvu/p/18041908

相关文章

  • CodeForces 1844H Multiple of Three Cycles
    洛谷传送门CF传送门首先环是不用管的,只用判环长是否为\(3\)的倍数即可。考虑设\(f(x,y,z)\)表示\(x\)个\(1\)链,\(y\)个\(2\)链,\(z\)个\(0\)链,组成所有环长都为\(3\)的倍数的方案数。注意到\(f(x,y,z)=(x+y+z)f(x,y,z-1)\)(可以接到剩下的任意......
  • Codeforces Round 929 (Div. 3)
    B.TurtleMath:FastThreeTask数学#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1e5+10;inta[N];voidsolve(){ intn; cin>>n; intsum=0; map<int,int>mp; intmx=0; for(inti=1;i<=n;i++){ cin......
  • 11 .Codeforces Round 891 (Div. 3)E. Power of Points(推公式+前缀和优化)
    E.PowerofPoints题解参考#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(inti=(a);i>=(b);--i)#define_for(i,a,b)for(inti=(a);i<(b);++i)#definepii......
  • Codeforces Round 929 (Div. 3) 题解(D-G)
    比赛链接:https://codeforces.com/contest/1933官解暂未放出。质量不错的一场D3。CF1933D.TurtleTenacity:ContinualMods题意将数组\(a_{1..n}\ge1\)重排,问是否能使\(((a_1\mathbin{\rmmod}a_2)\mathbin{\rmmod}a_3)\cdots\mathbin{\rmmod}a_n\ne0\)......
  • Codeforces Round 929 (Div. 3)
    CodeforcesRound929(Div.3)比赛链接A.TurtlePuzzle:RearrangeandNegate思路根据题意,很明显数组中所有元素的绝对值总和就是答案Code#include<bits/stdc++.h>usingnamespacestd;#defineall(x)x.begin()+1,x.end()#defineintlonglongvoidsolve(){......
  • Codeforces 441E Valera and Number
    首先看到\(\times2\)\(+1\)和最后答案的计算方式,能想到看成二进制来处理。考虑到\(\times2\)就是在最后加了一个\(0\)。不妨倒过来看,\(\times2\)就相当于舍弃了最低位。于是可以考虑\(\text{DP}\),\(f_{i,j}\)为考虑后面的\(i\)个操作,目前\(+\)的值为\(j\)的......
  • Codeforces 1705F Mark and the Online Exam
    先问全\(\texttt{T}\),记得到的数为\(a\)。接下来问\(len\)个位置为\(\texttt{T}\),得到的数为\(b\)。因为剩下\(n-len\)个位置肯定都会被刚好算上一次,对于这\(len\)个数里的\(\texttt{T}\)的个数\(x\)就有式子\((n-len)+2x=a+b\),可以解得\(x=\frac{......
  • Codeforces 286E Ladies' Shop
    考虑\(p_i\)满足什么不会被选。令当前选出来的\(p_j\)的集合为\(S\)。能发现当用\(S\)中的数能够凑(可多选,可选重)出\(p_i\)时\(p_i\)就不会被选。考虑凑出\(p_i\)的最后一步所用的\(2\)个数\(x+y=p_i\)。因为这\(2\)个数一定能被\(S\)中的数凑出且题目......
  • Codeforces Round 909 (Div
    CodeforcesRound909(Div.3)A.GamewithIntegers显然就是还要不是三的倍数就能赢!intn; cin>>n; intk; while(n--) { cin>>k; if(k%3==0){ cout<<"Second"<<endl; }else{ cout<<"First"<<endl; } }B......
  • Codeforces Round 905 (Div
    CodeforcesRound905(Div.3)A.Morning此题将其看为光标一直移动,其中移动次数就是坐标之差的绝对值,0看做10,由于其显示也需一次操作,所以加上四。#include<bits/stdc++.h>usingnamespacestd;intmain(){ intt; cin>>t; while(t--) { intarr[4],count=0; ......