题目大意
有 n 个块,编号从 1 到 n,每个块上有一个初始整数 a_i。
对于一个连续段 [l, r],如果整数 d (0 ≤ d ≤ r - l) 满足 min(al,al+1,...,al+d)=d,则称 d 为 nasty 数字。
一个段的 nastiness 定义为该段中 nasty 数字的数量。
需要处理 q 个操作:
对于每个操作 2,输出对应段的 nastiness 值。
思路讲解
我们发现一件事情,令 $mn\gets min(a_l, a_{l+1}, …, a_{l+d}) ,d\uparrow,mn\downarrow$,他们两个的这个单调关系是相反的,我们却要求的是 mn=d 的这个情况的数量,由于 d 是严格递增的,mn 是非严格递减的,这两者显然最多只有一个交点。
那么现在这个问题就来到了,我们实际上就是求一个区间中是否有这个 d 值嘛,显然,这个可以使用二分解决,只要我们有一个数据结构可以支持这个 RMQ 和这个单点修改即可,可以使用我们的树状数组。
AC代码
AC
https://codeforces.com/contest/2184/submission/358028437
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#include <bits/stdc++.h> #include <ranges> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<":"<<var<<"\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using LD = long double;
using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1; static constexpr ll mod = 998244353; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT;
struct RMQ{ const ll dummy=INF; ll n;vector<ll> tr;vector<ll> origin; inline ll lowbit(const ll &x){ return x&-x; } private: ll op(const ll &a,const ll &b){ return min(a,b); } public: RMQ(ll n){ this->n=n+2; tr.resize(n+5,INF),origin.resize(n+5); } ll query(ll l,ll r){ ll res=dummy; while (r>=l) { res=op(origin[r],res); r--; for(;r-lowbit(r)>=l;r-=lowbit(r)){ res=op(res, tr[r]); } } return res; } void upd(ll p,ll x){ origin[p]=x; for(int i=p;i<=n;i+=lowbit(i)){ tr[i]=origin[i]; for(int j=1;j<lowbit(i);j<<=1){ tr[i]=op(tr[i],tr[i-j]); } } } }; void Solve() { ll N,Q; cin >> N >> Q; vector<ll> A(N+2); for (int i=1;i<=N;++i) { cin>>A[i]; } RMQ tr(N); for (int i=1;i<=N;++i) { tr.upd(i,A[i]); } for (int _=1;_<=Q;++_) { ll op; cin>>op; if (op==1) { ll pos,x; cin>>pos>>x; tr.upd(pos,x); }else { ll l,r; cin>>l>>r; ll bsl=0,bsr=r-l; auto check=[&](ll x) { ll mn=tr.query(l,l+x); if (mn>x) { return 0; } if (mn==x) return 1; return 2; }; while (bsl<bsr) { ll mid=(bsl+bsr)>>1; if (check(mid)) { bsr=mid; }else { bsl=mid+1; } } if (check(bsl)==1) { cout<<1<<"\n"; }else { cout<<0<<"\n"; } } } }
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> lT; while(lT--) Solve(); return 0; }
|
心路历程(WA,TLE,MLE……)