一眼看上去,似乎是个和之前一样的板子,然后再一看。。。
...为啥还有区间要求???
万恶之源 \(\Rightarrow [l,r] \huge{[l,r]}\)
然后,事情就变得不简单了。。。
不就是个 \(250\) 行呗。。。
不就是个线段树上每一个区间节点上套一个 \(splay\;tree\) 呗。。。
不就是死活调不对呗。。。
不就是输出一堆 \(2147483647\) 呗。。。
不就是。。。。
当我精神几近崩溃的时候,\(zxb\) 出现,他是来拯救我的。。。
用双指针
。。。。
将其赶走之后,在历经下午,晚上,早读,上午将近 \(6\) 小时的努力下,终于。。。。
(此处省略 \(10000\) 字,请自行脑补)
但最后凭借坚强的毅力 f**k调试法,终于调出了样例,本以为会 然而却, \(\huge{\text{心中狂喜}}\)
然鹅连luogu最差解都算不上
主要做法就是对于整个序列建造一颗线段树,用来划分区间。
之后对于整个序列进行一个建树操作,就可以建造出每一个可行序列。
在每个序列当中,并不需要有什么权值。
只需要一个 \(root\) 来维护 \(splay\;tree\) 的根。
这样每一个 \(splay\;tree\) 就可以划分清楚,互不干扰。
建树的时候在每个点再建造一棵 \(splay\;tree\) 用来维护那要求的 \(5\) 个操作,记得还要 \(insert\) 一个 \(2147483647\) 防止找不到 \(pre\) 和 \(next\)
之后的 \(kth\) \(rank\) \(rotatr\) \(splay\) \(search\) \(pre\) \(next\) \(del\) 操作就大同小异了,其实就是在需要使用根节点的函数多传一个 \(node\) 参数用来区分。
然后线段树操作也就是 \(segins\) \(segkth\) \(segrk\) \(segpre\) \(segnext\) \(build\)
也就是将近20个函数,一点都不多。。。
真 不多
然后就可以开始漫长的 \(debug\) 过程了,这才是全部的 \(90%\) 才对。。。
当你这道题目调试完看到时,比做出任何一道题都有成就感。。。
所以来 \(k\) \(k\) 我的小代码ba。。。。
#include<bits/stdc++.h> using namespace std; //#define int long long #define debug cout<<"debug"<<endl #define freopen eat2 = freopen #define scanf eat1 = scanf #define INF 2147483647 #define inf INF #define cao cout<<endl namespace xin_io { #define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++ #define scanf eat1 = scanf #define freopen eat2 = freopen char buf[1<<20],*p1 = buf,*p2 = buf;FILE *eat2; inline void openfile() {freopen("t.txt","r",stdin);} inline void outfile(){freopen("o.txt","w",stdout);} inline int get() { int s = 0,f = 1;register char ch = gc(); while(!isdigit(ch)) {if(ch == '-') f = -1;ch = gc();} while(isdigit(ch)) {s = s * 10 + ch - '0';ch = gc();}return s * f; } } using namespace xin_io; int eat1; static const int maxn = 1e6+10,mod = 1e6; inline int min(int x,int y) {return x > y ? y : x;} inline int max(int x,int y) {return x > y ? x : y;} #define ls(x) t[x].son[0] #define rs(x) t[x].son[1] namespace xin { #define pushup(x) t[x].size = t[ls(x)].size + t[rs(x)].size + t[x].tot class xin_splay{public:int size, tot, val,son[2],fa;}t[maxn * 50]; int rt[maxn]; int a[maxn], n, m, cnt; inline void rotate(int x) { register int y = t[x].fa,z = t[y].fa; register int ki = t[y].son[1] == x; t[z].son[t[z].son[1] == y] = x; t[x].fa = z; t[y].son[ki] = t[x].son[ki xor 1]; t[t[x].son[ki xor 1]].fa = y; t[x].son[ki xor 1] = y; t[y].fa = x; pushup(y); pushup(x); } inline void splay( int x, int goal, int node ) { while( t[x].fa != goal ) { int y = t[x].fa,z = t[y].fa; if(z != goal) (t[z].son[1] == y) ^ (t[y].son[1] == x) ? rotate(x) : rotate(y); rotate(x); } if(!goal) rt[node] = x; } inline int init( int v, int fa ) {t[++cnt].val = v, t[cnt].fa = fa, t[cnt].tot = 1;pushup(cnt); return cnt;} inline void insert( int x, int node ) { int u = rt[node],fa = 0; if(!u) { u = init(x, 0), rt[node] = u; return ;} while(u and t[u].val != x) fa = u, u = t[u].son[t[u].val < x]; if(u) t[u].tot ++; else { u = init(x, fa); if(fa) t[fa].son[t[fa].val < x] = u; } splay(u,0,node ); } inline void search( int x, int node) { int u = rt[node]; if(!u) return ; while( t[u].son[t[u].val < x] and t[u].val != x) u = t[u].son[t[u].val < x]; splay( u, 0, node ); } inline int next( int x, int typ, int node ) { search(x, node); int u = rt[node]; if((typ and t[u].val < x) || (!typ and t[u].val > x)) return u; u = t[u].son[typ ^ 1]; while(t[u].son[typ]) u = t[u].son[typ]; return u; } inline void del( int x, int node) { int u = rt[node], pre = next(x, 1, node), nxt = next(x,0,node); splay(nxt, 0, node); splay(pre, nxt, node); int pos = t[pre].son[1]; if(t[pos].tot > 1) -- t[pos].tot, splay(pos, 0, node); else t[pre].son[1] = 0; pushup(pre); } inline void build(int node,int l,int r) { insert(inf,node); insert(-inf,node); if(l == r) return; register int mid = (l + r) >> 1; build(node<<1,l,mid); build(node << 1| 1,mid+1,r); } inline void segins(int node,int l,int r,int k,int val) { register int mid = (l + r) >> 1; insert(val,node);if(l == r) return ; if(mid >= k) segins(node << 1,l,mid,k,val); else segins(node << 1| 1,mid+1,r,k,val); } inline int segrk(int node,int l,int r,int k,int ql,int qr) { if(qr < l or ql > r) return 0; if(ql <= l and qr >= r) { search(k,node); register int u = rt[node]; if(t[u].val >= k) return t[ls(u)].size - 1; else return t[ls(u)].size + t[u].tot - 1; } // cout<<node<<' '<<l<<' '<<r<<endl; register int mid = (l + r) >> 1; return segrk(node << 1,l,mid,k,ql,qr) + segrk(node << 1| 1,mid+1,r,k,ql,qr); } inline void segupd(int node,int l,int r,int pos,int val) { del(a[pos],node); insert(val,node); if(l == r and r == pos) {a[pos] = val;return ;} register int mid = (l + r ) >> 1; if(mid >= pos) segupd(node << 1,l,mid,pos,val); else segupd(node << 1| 1,mid+1,r,pos,val); } inline int segnxt(int node,int l,int r,int ql,int qr,int k) { if(l > qr or r < ql) return inf; if(l >= ql and r <= qr) return t[next(k,0,node)].val; register int mid = (l + r )>> 1; return min(segnxt(node << 1,l,mid,ql,qr,k) , segnxt(node << 1 | 1,mid + 1,r,ql,qr,k)); } inline int segpre(int node,int l,int r,int ql,int qr,int k) { if(l > qr or r < ql) return -inf; if(l >= ql and r <= qr) return t[next(k,1,node)].val; register int mid = (l + r) >> 1; return max(segpre(node << 1,l,mid,ql,qr,k) , segpre(node << 1| 1,mid+1,r,ql,qr,k)); } inline int segkth(int ql,int qr,int k) { register int l = 0,r = 1e8,ret; while(l <= r) { register int mid = (l + r) >> 1; register int judge = segrk(1,1,n,mid,ql,qr) + 1; if(judge > k) r = mid - 1; else l = mid + 1, ret = mid; } return ret; } inline void check() { for(register int i=1;i<=cnt;++i) cout<<"i = "<<i<<" t[i].val = "<<t[i].val<<" t[i].size = "<<t[i].size<<endl; cout<<endl; } inline short main() { #ifndef ONLINE_JUDGE openfile(); #endif n = get(); m = get(); build(1,1,n); // check(); for(register int i=1;i<=n;++i) a[i] = get(),segins(1,1,n,i,a[i]); // check(); for(register int i=1;i<=m;++i) { register int op = get(); if(op == 1) { register int l = get(),r = get(),x = get(); printf("%d\n",segrk(1,1,n,x,l,r) + 1); } if(op == 2) { register int l = get(),r = get(),k = get(); printf("%d\n",segkth(l,r,k)); } if(op == 3) { register int pos = get(),x = get(); segupd(1,1,n,pos,x); } if(op == 4) { register int l = get(),r = get(),x = get(); printf("%d\n",segpre(1,1,n,l,r,x)); } if(op == 5) { register int l = get(),r = get(),x = get(); printf("%d\n",segnxt(1,1,n,l,r,x)); } } return 0; } } signed main() {return xin::main();}
\(\huge{\color{red}{\text{真好玩}}}\)