求调线段树套fhq

P3380 【模板】树套树

```cpp /* Author: EnderDeer Online Judge: Luogu */ #include<bits/stdc++.h> #define int long long #define mem(x) memset(x,0,sizeof(x)) using namespace std; int read(){ int s = 0,w = 1; char ch = getchar(); while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();} while(ch >= '0' && ch <= '9')s = s * 10 + ch - '0',ch = getchar(); return s * w; } mt19937 rnd(time(0)); struct nodeee{ int l; int r; }ee[1000010]; struct node{ int l; int r; int w; int key; int siz; }e[50010 * 40]; struct nodee{ int cnt,rt; int newnode(int w){ cnt ++; e[cnt].w = w; e[cnt].key = rnd(); e[cnt].siz = 1; return cnt; } void update(int i){ e[i].siz = e[e[i].l].siz + e[e[i].r].siz + 1; } void split(int i,int w,int &x,int &y){ if(!i){ x = y = 0; return ; } if(e[i].w <= w){ x = i; split(e[i].r,w,e[i].r,y); } else { y = i; split(e[i].l,w,x,e[i].l); } update(i); } int merge(int x,int y){ if(!x || !y)return x + y; if(e[x].key > e[y].key){ e[x].r = merge(e[x].r,y); update(x); return x; } else { e[y].l = merge(x,e[y].l); update(y); return y; } } int x,y,z; void ins(int w){ split(rt,w,x,y); rt = merge(merge(x,newnode(w)),y); } void del(int w){ split(rt,w,x,z); split(x,w - 1,x,y); y = merge(e[y].l,e[y].r); rt = merge(merge(x,y),z); } int getrank(int w){ split(rt,w - 1,x,y); int ans = e[x].siz + 1; rt = merge(x,y); return ans; } int getnum(int rk){ int now = rt; while(now){ if(e[e[now].l].siz + 1 == rk)break; else if(e[e[now].l].siz >= rk)now = e[now].l; else { rk -= e[e[now].l].siz + 1; now = e[now].r; } } return e[now].w; } int pre(int w){ split(rt,w - 1,x,y); int now = x; while(e[now].r)now = e[now].r; int ans = e[now].w; rt = merge(x,y); return ans; } int nxt(int w){ split(rt,w,x,y); int now = y; while(e[now].l)now = e[now].l; int ans = e[now].w; rt = merge(x,y); return ans; } }t[100010]; int n,m; int a[1000010]; void build(int i,int l,int r){ for(int ii = l;ii <= r;ii ++)t[i].ins(a[ii]); ee[i].l = l; ee[i].r = r; if(l == r)return ; int mid = (l + r) / 2; build(i * 2,l,mid); build(i * 2 + 1,mid + 1,r); } int queryrk(int i,int l,int r,int w){ if(l <= ee[i].l && ee[i].r <= r)return t[i].getrank(w) - 1; int ans = 0; int mid = (l + r) / 2; if(r <= mid)ans = queryrk(i * 2,l,r,w); else if(l > mid)ans = queryrk(i * 2 + 1,l,r,w); else ans = queryrk(i * 2,l,mid,w) + queryrk(i * 2 + 1,mid + 1,r,w); return ans; } int queryw(int l,int r,int w){ int ll = 0,rr = 2147483647,ans = -1; int mid; while(ll < rr){ mid = (ll + rr) / 2; if(queryrk(1,l,r,mid) + 1 <= w){ ans = mid; ll = mid + 1; } else rr = mid - 1; } return ans; } void update(int i,int pos,int w){ t[i].del(a[pos]); t[i].ins(w); if(ee[i].l == ee[i].r){ a[pos] = w; return ; } int mid = (ee[i].l + ee[i].r) / 2; if(pos <= mid)update(i * 2,pos,w); else update(i * 2 + 1,pos,w); } int querypre(int i,int l,int r,int w){ if(l >= ee[i].l && ee[i].r >= r)return t[i].pre(w); int ans = -2147483647; int mid = (l + r) / 2; if(r <= mid)ans = max(ans,querypre(i * 2,l,r,w)); else if(l > mid)ans = max(ans,querypre(i * 2 + 1,l,r,w)); else ans = max(ans,max(querypre(i * 2,l,mid,w),querypre(i * 2 + 1,mid + 1,r,w))); return ans; } int querynxt(int i,int l,int r,int w){ if(ee[i].l >= l && ee[i].r <= r)return t[i].nxt(w); int ans = 2147483647; int mid = (l + r) / 2; if(r <= mid)ans = min(ans,querynxt(i * 2,l,r,w)); else if(l > mid)ans = min(ans,querynxt(i * 2 + 1,l,r,w)); else ans = min(ans,min(querynxt(i * 2,l,mid,w),querynxt(i * 2 + 1,mid + 1,r,w))); return ans; } signed main(){ cin>>n>>m; for(int i = 1;i <= n;i ++)a[i] = read(); build(1,1,n); while(m --){ int op; int x,y,w; op = read(); if(op == 1){ x = read(),y = read(),w = read(); printf("%lld\n",queryrk(1,x,y,w)); } if(op == 2){ x = read(),y = read(),w = read(); printf("%lld\n",queryw(x,y,w)); } if(op == 3){ x = read(),w = read(); update(1,x,w); } if(op == 4){ x = read(),y = read(),w = read(); printf("%lld\n",querypre(1,x,y,w)); } if(op == 5){ x = read(),y = read(),w = read(); printf("%lld\n",querynxt(1,x,y,w)); } } return 0; } ```
by EDqwq @ 2021-03-05 20:11:51


@[林深时x见鹿](/user/294562) 草,这题当时我从中午写到晚上
by Diaоsi @ 2021-03-05 21:57:04


@[Diaоsi](/user/137242) 有兴趣调下吗![qiang](https://cdn.luogu.com.cn/upload/pic/62236.png)
by EDqwq @ 2021-03-05 22:12:26


@[林深时x见鹿](/user/294562) 你平衡树新建结点炸了 e 是公共的,但是 cnt 不是
by Rui_R @ 2021-03-06 11:44:25


导致新建节点很有可能会拿走之前已经分配掉的结点,就炸了
by Rui_R @ 2021-03-06 11:45:16


@[林深时x见鹿](/user/294562) queryrk 里面 ``` int mid = (l + r) / 2; if (r <= mid)ans = queryrk(i * 2, l, r, w); else if (l > mid)ans = queryrk(i * 2 + 1, l, r, w); else ans = queryrk(i * 2, l, mid, w) + queryrk(i * 2 + 1, mid + 1, r, w); ``` 这段你仔细看看
by Rui_R @ 2021-03-06 11:48:35


@[Rui_R](/user/101984) 啊,完蛋,我新的代码没发上来
by EDqwq @ 2021-03-06 11:48:40


```cpp /* Author: EnderDeer Online Judge: Luogu */ #include<bits/stdc++.h> #define int long long #define mem(x) memset(x,0,sizeof(x)) using namespace std; int read(){ int s = 0,w = 1; char ch = getchar(); while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();} while(ch >= '0' && ch <= '9')s = s * 10 + ch - '0',ch = getchar(); return s * w; } mt19937 rnd(time(0)); struct nodeee{ int l; int r; }ee[1000010]; struct node{ int l; int r; int w; int key; int siz; }e[50010 * 40]; int cnt,rt; int newnode(int w){ cnt ++; e[cnt].w = w; e[cnt].key = rnd(); e[cnt].siz = 1; return cnt; } void update(int i){ e[i].siz = e[e[i].l].siz + e[e[i].r].siz + 1; } void split(int i,int w,int &x,int &y){ if(!i){ x = y = 0; return ; } if(e[i].w <= w){ x = i; split(e[i].r,w,e[i].r,y); } else { y = i; split(e[i].l,w,x,e[i].l); } update(i); } int merge(int x,int y){ if(!x || !y)return x + y; if(e[x].key > e[y].key){ e[x].r = merge(e[x].r,y); update(x); return x; } else { e[y].l = merge(x,e[y].l); update(y); return y; } } struct nodee{ int x,y,z; void ins(int w){ split(rt,w,x,y); rt = merge(merge(x,newnode(w)),y); } void del(int w){ split(rt,w,x,z); split(x,w - 1,x,y); y = merge(e[y].l,e[y].r); rt = merge(merge(x,y),z); } int getrank(int w){ split(rt,w - 1,x,y); int ans = e[x].siz + 1; rt = merge(x,y); return ans; } int getnum(int rk){ int now = rt; while(now){ if(e[e[now].l].siz + 1 == rk)break; else if(e[e[now].l].siz >= rk)now = e[now].l; else { rk -= e[e[now].l].siz + 1; now = e[now].r; } } return e[now].w; } int pre(int w){ split(rt,w - 1,x,y); int now = x; while(e[now].r)now = e[now].r; int ans = e[now].w; rt = merge(x,y); return ans; } int nxt(int w){ split(rt,w,x,y); int now = y; while(e[now].l)now = e[now].l; int ans = e[now].w; rt = merge(x,y); return ans; } }t[100010]; int n,m; int a[1000010]; void build(int i,int l,int r){ for(int ii = l;ii <= r;ii ++)t[i].ins(a[ii]); ee[i].l = l; ee[i].r = r; if(l == r)return ; int mid = (l + r) / 2; build(i * 2,l,mid); build(i * 2 + 1,mid + 1,r); } int queryrk(int i,int l,int r,int w){ if(l <= ee[i].l && ee[i].r <= r)return t[i].getrank(w) - 1; int ans = 0; int mid = (l + r) / 2; if(r <= mid)ans = queryrk(i * 2,l,r,w); else if(l > mid)ans = queryrk(i * 2 + 1,l,r,w); else ans = queryrk(i * 2,l,mid,w) + queryrk(i * 2 + 1,mid + 1,r,w); return ans; } int queryw(int l,int r,int w){ int ll = 0,rr = 2147483647,ans = -1; int mid; while(ll < rr){ mid = (ll + rr) / 2; if(queryrk(1,l,r,mid) + 1 <= w){ ans = mid; ll = mid + 1; } else rr = mid - 1; } return ans; } void update(int i,int pos,int w){ t[i].del(a[pos]); t[i].ins(w); if(ee[i].l == ee[i].r){ a[pos] = w; return ; } int mid = (ee[i].l + ee[i].r) / 2; if(pos <= mid)update(i * 2,pos,w); else update(i * 2 + 1,pos,w); } int querypre(int i,int l,int r,int w){ if(l >= ee[i].l && ee[i].r >= r)return t[i].pre(w); int ans = -2147483647; int mid = (l + r) / 2; if(r <= mid)ans = max(ans,querypre(i * 2,l,r,w)); else if(l > mid)ans = max(ans,querypre(i * 2 + 1,l,r,w)); else ans = max(ans,max(querypre(i * 2,l,mid,w),querypre(i * 2 + 1,mid + 1,r,w))); return ans; } int querynxt(int i,int l,int r,int w){ if(ee[i].l >= l && ee[i].r <= r)return t[i].nxt(w); int ans = 2147483647; int mid = (l + r) / 2; if(r <= mid)ans = min(ans,querynxt(i * 2,l,r,w)); else if(l > mid)ans = min(ans,querynxt(i * 2 + 1,l,r,w)); else ans = min(ans,min(querynxt(i * 2,l,mid,w),querynxt(i * 2 + 1,mid + 1,r,w))); return ans; } signed main(){ cin>>n>>m; for(int i = 1;i <= n;i ++)a[i] = read(); build(1,1,n); while(m --){ int op; int x,y,w; op = read(); if(op == 1){ x = read(),y = read(),w = read(); printf("%lld\n",queryrk(1,x,y,w)); } if(op == 2){ x = read(),y = read(),w = read(); printf("%lld\n",queryw(x,y,w)); } if(op == 3){ x = read(),w = read(); update(1,x,w); } if(op == 4){ x = read(),y = read(),w = read(); printf("%lld\n",querypre(1,x,y,w)); } if(op == 5){ x = read(),y = read(),w = read(); printf("%lld\n",querynxt(1,x,y,w)); } } return 0; } ```
by EDqwq @ 2021-03-06 11:48:54


你说的这个问题已经解决了,但是仍然错误 怀疑是平衡树问题,但我没有证据
by EDqwq @ 2021-03-06 11:49:38


哦你好像所有地方都是这么写的,你用力改一下
by Rui_R @ 2021-03-06 11:50:08


| 下一页