请求开大时限放 FHQ Treap 套线段树过

P3380 【模板】树套树

题解代码: ```cpp #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 5e4 + 5, MAXM = 1e7; const int INF = 0x7fffffff; int a[MAXN]; int n, m; int val[MAXM], sz[MAXM], heap[MAXM], l[MAXM], r[MAXM]; int tot; struct FHQ_Treap { int root; inline void Update(int x) { sz[x] = sz[l[x]] + sz[r[x]] + 1; return; } inline int Merge(int x, int y) { if (!x || !y) return x + y; if (heap[x] < heap[y]) return r[x] = Merge(r[x], y), Update(x), x; return l[y] = Merge(x, l[y]), Update(y), y; } inline void Split(int x, int key, int &u, int &v) { if (!x) { u = v = 0; return; } if (val[x] <= key) u = x, Split(r[x], key, r[u], v); else v = x, Split(l[x], key, u, l[v]); Update(x); return; } inline int Create(int key) { val[++tot] = key, heap[tot] = rand(), sz[tot] = 1; return tot; } int x, y, z; inline void Insert(int key) { Split(root, key, x, y); root = Merge(x, Merge(Create(key), y)); return; } inline void Delete(int key) { Split(root, key, x, z); Split(x, key - 1, x, y); y = Merge(l[y], r[y]); root = Merge(x, Merge(y, z)); return; } inline int FindRank(int key) { Split(root, key - 1, x, y); int ans = sz[x] + 1; root = Merge(x, y); return ans; } inline void Build(int l, int r) { for (int i = l; i <= r; i++) Insert(a[i]); return; } inline int FindKey(int x, int rak) { if (rak <= sz[l[x]]) return FindKey(l[x], rak); if (rak == sz[l[x]] + 1) return val[x]; return FindKey(r[x], rak - sz[l[x]] - 1); } inline int Lower(int key) { Split(root, key - 1, x, y); int ans; if (sz[x]) ans = FindKey(x, sz[x]); else ans = -INF; root = Merge(x, y); return ans; } inline int Upper(int key) { Split(root, key, x, y); int ans; if (sz[y]) ans = FindKey(y, 1); else ans = INF; root = Merge(x, y); return ans; } } FT[MAXN << 2]; #define mid ((x + y) >> 1) #define lson (pst << 1) #define rson (pst << 1 | 1) struct SegmentTree { int root[MAXN << 2]; inline void Build(int x, int y, int pst) { FT[pst].Build(x, y); if (x != y) Build(x, mid, lson), Build(mid + 1, y, rson); return; } inline int QueryRank(int x, int y, int pst, int l, int r, int key) { if (y < l || x > r) return 0; if (l <= x && y <= r) return FT[pst].FindRank(key) - 1; return QueryRank(x, mid, lson, l, r, key) + QueryRank(mid + 1, y, rson, l, r, key); } inline int QueryKey(int l, int r, int rak) { int x = 0, y = 1e8, ans = -1; while (x <= y) { if (QueryRank(1, n, 1, l, r, mid) + 1 <= rak) ans = mid, x = mid + 1; else y = mid - 1; } return ans; } inline void Update(int x, int y, int pst, int p, int k) { FT[pst].Delete(a[p]); FT[pst].Insert(k); if (x != y) { if (p <= mid) Update(x, mid, lson, p, k); else Update(mid + 1, y, rson, p, k); } return; } inline int Lower(int x, int y, int pst, int l, int r, int k) { if (y < l || x > r) return -INF; if (l <= x && y <= r) return FT[pst].Lower(k); return max(Lower(x, mid, lson, l, r, k), Lower(mid + 1, y, rson, l, r, k)); } inline int Upper(int x, int y, int pst, int l, int r, int k) { if (y < l || x > r) return INF; if (l <= x && y <= r) return FT[pst].Upper(k); return min(Upper(x, mid, lson, l, r, k), Upper(mid + 1, y, rson, l, r, k)); } } ST; signed main(void) { cin >> n >> m; for (int i = 1; i <= n; i++) scanf("%d", a + i); ST.Build(1, n, 1); for (int i = 1, opt, l, r, p, k; i <= m; i++) { scanf("%d", &opt); if (opt == 1) { scanf("%d %d %d", &l, &r, &k); printf("%d\n", ST.QueryRank(1, n, 1, l, r, k) + 1); } if (opt == 2) { scanf("%d %d %d", &l, &r, &k); printf("%d\n", ST.QueryKey(l, r, k)); } if (opt == 3) { scanf("%d %d", &p, &k); ST.Update(1, n, 1, p, k); a[p] = k; } if (opt == 4) { scanf("%d %d %d", &l, &r, &k); printf("%d\n", ST.Lower(1, n, 1, l, r, k)); } if (opt == 5) { scanf("%d %d %d", &l, &r, &k); printf("%d\n", ST.Upper(1, n, 1, l, r, k)); } } return 0; } ``` 本人代码: ```cpp #include<bits/stdc++.h> #define INF 2147483647 #define MAXN 2000000 #define MOD 998244353 #define ls son[rt][0] #define rs son[rt][1] #define il inline #define rg register using namespace std; namespace io { const int __SIZE = (1 << 21) + 1; char ibuf[__SIZE], *iS, *iT, obuf[__SIZE], *oS = obuf, *oT = oS + __SIZE - 1, __c, qu[55]; int __f, qr, _eof; #define Gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, __SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++) inline void flush () { fwrite (obuf, 1, oS - obuf, stdout), oS = obuf; } inline void gc (char &x) { x = Gc(); } inline void pc (char x) { *oS ++ = x; if (oS == oT) flush (); } inline void pstr (const char *s) { int __len = strlen(s); for (__f = 0; __f < __len; ++__f) pc (s[__f]); } inline void gstr (char *s) { for(__c = Gc(); __c < 32 || __c > 126 || __c == ' ';) __c = Gc(); for(; __c > 31 && __c < 127 && __c != ' ' && __c != '\n' && __c != '\r'; ++s, __c = Gc()) *s = __c; *s = 0; } template <class I> inline bool gi (I &x) { _eof = 0; for (__f = 1, __c = Gc(); (__c < '0' || __c > '9') && !_eof; __c = Gc()) { if (__c == '-') __f = -1; _eof |= __c == EOF; } for (x = 0; __c <= '9' && __c >= '0' && !_eof; __c = Gc()) x = x * 10 + (__c & 15), _eof |= __c == EOF; x *= __f; return !_eof; } template <class I> inline void print (I x) { if (!x) pc ('0'); if (x < 0) pc ('-'), x = -x; while (x) qu[++ qr] = x % 10 + '0', x /= 10; while (qr) pc (qu[qr --]); } struct Flusher_ {~Flusher_(){flush();}}io_flusher_; } using io::pc; using io::gc; using io::pstr; using io::gstr; using io::gi; using io::print; int val[MAXN+5],sz[MAXN+5],key[MAXN+5],son[MAXN+5][2],tot; unsigned seed=std::chrono::system_clock::now().time_since_epoch().count(); mt19937 rand_num(seed); il void pushup(int rt){sz[rt]=sz[ls]+sz[rs]+1;} il void split(int rt,int k,int &a,int &b){ if(!rt) a=b=0; else{ if(val[rt]<=k) a=rt,split(rs,k,rs,b); else b=rt,split(ls,k,a,ls); pushup(rt); } }il int merge(int a,int b){ if(!a||!b) return a+b; if(key[a]>key[b]){ son[a][1]=merge(son[a][1],b); pushup(a); return a; }else{ son[b][0]=merge(a,son[b][0]); pushup(b); return b; } }int rand(){return rand_num();} il int newnode(int v){val[++tot]=v,sz[tot]=1,key[tot]=rand(); return tot;} il int kth(int rt,int x){ while(1){ if(x<=sz[ls]) rt=ls; else if(x==sz[ls]+1) return val[rt]; else x-=(sz[ls]+1),rt=rs; } }il void ins(int &rt,int x){ int a,b; split(rt,x,a,b); rt=merge(merge(a,newnode(x)),b); }il void del(int &rt,int v){ int a,b,c; split(rt,v,a,b),split(a,v-1,a,c); c=merge(son[c][0],son[c][1]); rt=merge(merge(a,c),b); }il int findpre(int &rt,int v){ int a,b,p; split(rt,v-1,a,b); p=a; if(!sz[a]){rt=merge(a,b); return -INF;} while(son[a][1]) a=son[a][1]; rt=merge(p,b); return val[a]; }il int findnxt(int &rt,int v){ int a,b,p; split(rt,v,a,b); p=b; if(!sz[b]){rt=merge(a,b); return INF;} while(son[b][0]) b=son[b][0]; rt=merge(a,p); return val[b]; }il int getrank(int &rt,int v){ int a,b; split(rt,v-1,a,b); int ret=sz[a]+1; rt=merge(a,b); return ret; } #undef ls #undef rs int a[MAXN/10],n,Q; struct SegmentT{ #define ls (rt<<1) #define rs (rt<<1|1) int root[MAXN/10]; il void build(int rt,int l,int r){ for(int i=l;i<=r;i++) ins(root[rt],a[i]); if(l==r) return; rg int md=(l+r)>>1; build(ls,l,md),build(rs,md+1,r); }il int askrank(int rt,int l,int r,int L,int R,int v){ rg int md=(l+r)>>1,ret=0; if(L<=l&&r<=R) return getrank(root[rt],v)-1; if(L<=md) ret+=askrank(ls,l,md,L,R,v); if(R>md) ret+=askrank(rs,md+1,r,L,R,v); return ret; }il int askval(int L,int R,int k){ rg int l=0,r=1e8,ret=-1; while(l<=r){ int md=(l+r)>>1; if(askrank(1,1,n,L,R,md)+1<=k) ret=md,l=md+1; else r=md-1; }return ret; }il void change(int rt,int l,int r,int x,int v){ del(root[rt],a[x]),ins(root[rt],v); if(l==r) return; rg int md=(l+r)>>1; if(x<=md) change(ls,l,md,x,v); else change(rs,md+1,r,x,v); }il int pre(int rt,int l,int r,int L,int R,int v){ if(L<=l&&r<=R) return findpre(root[rt],v); rg int md=(l+r)>>1,ret=-INF; if(L<=md) ret=max(ret,pre(ls,l,md,L,R,v)); if(R>md) ret=max(ret,pre(rs,md+1,r,L,R,v)); return ret; }il int nxt(int rt,int l,int r,int L,int R,int v){ if(L<=l&&r<=R) return findnxt(root[rt],v); rg int md=(l+r)>>1,ret=INF; if(L<=md) ret=min(ret,nxt(ls,l,md,L,R,v)); if(R>md) ret=min(ret,nxt(rs,md+1,r,L,R,v)); return ret; } #undef ls #undef rs }T; signed main(){ freopen("Tree.in","r",stdin); freopen("Tree.out","w",stdout); srand(time(0)); gi(n),gi(Q); for(rg int i=1;i<=n;i++) gi(a[i]); T.build(1,1,n); while(Q--){ int opt=1,l,r,k; gi(opt),gi(l),gi(r); if(opt!=3){ gi(k); if(opt==1) printf("%d\n",T.askrank(1,1,n,l,r,k)+1); if(opt==2) printf("%d\n",T.askval(l,r,k)); if(opt==4) printf("%d\n",T.pre(1,1,n,l,r,k)); if(opt==5) printf("%d\n",T.nxt(1,1,n,l,r,k)); }else T.change(1,1,n,l,r),a[l]=r; }return 0; } ```
by Yakurii @ 2021-11-16 21:16:01


@[CodyTheWolf](/user/29354)
by Yakurii @ 2021-11-16 21:16:26


@[BlackHeath](/user/439802) 所以 FHQ 到底是外层树还是内层树啊,看你表述没看懂
by DPair @ 2021-11-16 21:20:56


@[DPair](/user/66511) FHQ 是内层树啊...
by S00021 @ 2021-11-16 21:21:32


对不起表述有误,轻喷
by Yakurii @ 2021-11-16 21:22:43


@[DPair](/user/66511)
by Yakurii @ 2021-11-16 21:22:54


个人并不觉得这个做法有任何问题,我觉得应该是你自身常数比较大,或者复杂度本身就有问题不过你没分析出来而已 我看看
by DPair @ 2021-11-16 21:23:00


实测我读优+O2卡过去了) [记录](https://www.luogu.com.cn/record/62780598)
by CodyTheWolf @ 2021-11-16 21:27:58


我也这么写的但是开O2能过啊
by 时间重洗 @ 2021-11-16 21:28:03


谢谢,可能是我哪里复杂度假掉了((( 同样过不去dynamic rankings, 可以帮我看看哪里复杂度假了吗() 那个能过普通平衡树和加强版
by Yakurii @ 2021-11-16 21:31:51


| 下一页